开发手册 欢迎您!
软件开发者资料库

面向对象的Python - 高级功能

面向对象的Python高级功能 - 从简单和简单的步骤学习面向对象的Python,从基本到高级概念,包括简介,环境设置,数据结构,构建块,面向对象的快捷方式,继承和多态,Python设计模式,高级功能,文件和字符串,异常和异常类,对象序列化,Python库。

在此我们将研究Python提供的一些高级功能

我们的类设计中的核心语法

在这里我们将看看上,Python如何让我们在课堂上利用运算符. Python主要是对象和方法调用对象,即使它被一些方便的语法隐藏也是如此.

>>> var1 = 'Hello'>>> var2 = ' World!'>>> var1 + var2'Hello World!'>>>>>> var1.__add__(var2)'Hello World!'>>> num1 = 45>>> num2 = 60>>> num1.__add__(num2)105>>> var3 = ['a', 'b']>>> var4 = ['hello', ' John']>>> var3.__add__(var4)['a', 'b', 'hello', ' John']

所以,如果我们必须将魔术方法__add__添加到我们自己的类中,我们也可以这样做.让我们尝试这样做.

我们有一个名为Sumlist的类,它有一个构造函数__init__,它将列表作为一个名为my_list的参数.

class SumList(object):   def __init__(self, my_list):      self.mylist = my_list   def __add__(self, other):     new_list = [ x + y for x, y in zip(self.mylist, other.mylist)]     return SumList(new_list)      def __repr__(self):      return str(self.mylist)aa = SumList([3,6, 9, 12, 15])bb = SumList([100, 200, 300, 400, 500])cc = aa + bb # aa.__add__(bb)print(cc) # should gives us a list ([103, 206, 309, 412, 515])

输出

  [103,206,309,412 ,515]

但是有许多方法由其他魔术方法在内部管理.以下是其中一些,

'abc' in var # var.__contains__('abc')var == 'abc' # var.__eq__('abc')var[1] # var.__getitem__(1)var[1:3] # var.__getslice__(1, 3)len(var) # var.__len__()print(var) # var.__repr__()

继承自内置类型

类也可以从内置类型继承,这意味着从任何内置继承并利用那里找到的所有功能.

在下面的例子中我们是继承自字典但后来我们正在实现其方法之一__setitem__.当我们在字典中设置键和值时,会调用此(setitem).由于这是一种神奇的方法,因此将隐式调用.

class MyDict(dict):   def __setitem__(self, key, val):      print('setting a key and value!')      dict.__setitem__(self, key, val)dd = MyDict()dd['a'] = 10dd['b'] = 20for key in dd.keys():   print('{0} = {1}'.format(key, dd[key]))

输出

setting a key and value!setting a key and value!a = 10b = 20

让我们扩展前面的例子,下面我们调用了两个名为__getitem__和__setitem__的魔术方法,当调用时更好我们处理列表索引.

# Mylist inherits from 'list' object but indexes from 1 instead for 0!class Mylist(list): # inherits from list   def __getitem__(self, index):      if index == 0:         raise IndexError      if index > 0:         index = index - 1         return list.__getitem__(self, index) # this method is called when# we access a value with subscript like x[1]   def __setitem__(self, index, value):      if index == 0:         raise IndexError      if index > 0:      index = index - 1      list.__setitem__(self, index, value)x = Mylist(['a', 'b', 'c']) # __init__() inherited from builtin listprint(x) # __repr__() inherited from builtin listx.append('HELLO'); # append() inherited from builtin listprint(x[1]) # 'a' (Mylist.__getitem__ cutomizes list superclass               # method. index is 1, but reflects 0!print (x[4]) # 'HELLO' (index is 4 but reflects 3!

输出

['a', 'b', 'c']aHELLO

在上面的例子中,我们在Mylist中设置了一个三项列表,并且隐式调用__init__方法,当我们打印元素x时,我们得到三个项目列表(['a','b','c然后我们将另一个元素附加到此列表.稍后我们要求索引1和索引4.但是如果你看到输出,我们从(index-1)得到我们要求的元素.我们知道列表索引从0开始,但这里的索引从1开始(这就是为什么我们得到列表的第一项).

命名约定

在这里我们将研究我们将用于变量的名称,尤其是私有v全球Python程序员使用的ariables和约定.虽然变量被指定为私有,但Python中没有隐私,这是设计的.与任何其他记录良好的语言一样,Python具有它所推广的命名和样式约定,尽管它不会强制执行它们.有一个样式指南由Python的创始人" Guido van Rossum"编写,它描述了名称的最佳实践和使用,称为PEP8.以下是此链接,  https://www.python.org/dev/peps/pep-0008/

PEP代表Python增强提议,是一系列文档,分布在Python社区中以讨论提议的更改.例如,建议全部,

  • 模块名称 :  all_lower_case

  • 班级名称和例外名称 :  CamelCase

  • 全球和本地名称 :  all_lower_case

  • 函数和方法名称 :  all_lower_case

  • 常数和减号; ALL_UPPER_CASE

这些只是建议,如果您愿意,可以有所不同.但是由于大多数开发人员都遵循这些建议,所以我的代码可能性较差.

为什么符合惯例?

我们可以关注PEP建议我们允许我们获取,

  • 绝大多数开发人员更熟悉

  • 更清楚大多数读者的代码.

  • 将匹配在相同代码库上工作的其他贡献者的风格.

  • 专业软件开发人员的标记

  • 每个人都会接受你.

变量命名和减号; 'public'和'Private'

在Python中,当我们处理模块和类时,我们将一些变量或属性指定为私有.在Python中,不存在除了对象内部之外无法访问的"私有"实例变量.私有只是意味着它们根本不打算由代码的用户使用,而是打算在内部使用.通常,大多数Python开发人员都遵循一种约定,例如,以下划线为前缀的名称. _attrval(下面的示例)应被视为API或任何Python代码的非公共部分,无论它是函数,方法还是数据成员.以下是我们遵循的命名约定,

  • 公共属性或变量(供该模块的导入者使用或此类的用户) :   regular_lower_case

  • 私有属性或变量(模块或类的内部使用) :   _single_leading_underscore

  • 不应包含子类和减号的私有属性; __ double_leading_underscore

  • 魔术属性 : 号; __ double_underscores __ (使用它们,不要创建它们)

class GetSet(object):   instance_count = 0 # public      __mangled_name = 'no privacy!' # special variable   def __init__(self, value):      self._attrval = value # _attrval is for internal use only      GetSet.instance_count += 1   @property   def var(self):      print('Getting the "var" attribute')      return self._attrval   @var.setter   def var(self, value):      print('setting the "var" attribute')      self._attrval = value   @var.deleter   def var(self):      print('deleting the "var" attribute')      self._attrval = Nonecc = GetSet(5)cc.var = 10 # public nameprint(cc._attrval)print(cc._GetSet__mangled_name)

输出

setting the "var" attribute10no privacy!