目录

高级功能(Advanced Features)

在本文中,我们将介绍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__,它将list作为一个名为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])

输出 (Output)

[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'] = 10
dd['b'] = 20
for key in dd.keys():
   print('{0} = {1}'.format(key, dd[key]))

输出 (Output)

setting a key and value!
setting a key and value!
a = 10
b = 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 list
print(x) # __repr__() inherited from builtin list
x.append('HELLO'); # append() inherited from builtin list
print(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!

输出 (Output)

['a', 'b', 'c']
a
HELLO

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

命名约定

在这里,我们将研究我们将用于变量的名称,尤其是全球Python程序员使用的私有变量和约定。 虽然变量被指定为私有,但Python中没有隐私,这是设计的。 与任何其他记录良好的语言一样,Python具有它所推广的命名和样式约定,尽管它不会强制执行它们。 由Guido van Rossum” the originator of Python, that describe the best practices and use of name and is called PEP8. Here is the link for this,Guido van Rossum” the originator of Python, that describe the best practices and use of name and is called PEP8. Here is the link for this,编写的风格指南Guido van Rossum” the originator of Python, that describe the best practices and use of name and is called PEP8. Here is the link for this, Guido van Rossum” the originator of Python, that describe the best practices and use of name and is called PEP8. Here is the link for this, 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建议,

  • 对绝大多数开发人员来说比较熟悉
  • 更清楚大多数读者的代码。
  • 将匹配在相同代码库上工作的其他贡献者的风格。
  • 专业软件开发人员的标志
  • 每个人都会接受你。

变量命名 - “公共”和“私人”

在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 = None
cc = GetSet(5)
cc.var = 10 # public name
print(cc._attrval)
print(cc._GetSet__mangled_name)

输出 (Output)

setting the "var" attribute
10
no privacy!
↑回到顶部↑
WIKI教程 @2018