Object Oriented Python 简明教程
Object Oriented Python - Advanced Features
在此,我们将研究 Python 提供的部分高级特性
Core Syntax in our Class design
在此,我们将关注 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])
Inheriting From built-in types
类还可从内置类型继承,这意味着从任何内置类型继承并利用在其中发现的所有功能。
在以下示例中,我们正在从字典继承,但我们正在实现它的一种方法 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!
Naming Conventions
在此,我们将研究我们对变量(特别是私有变量)使用的名称以及全世界 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, https://www.python.org/dev/peps/pep-0008/ 编写的风格指南
PEP 代表 Python 增强提案,是一系列文档,在 Python 社区中分发,以讨论提议的更改。例如,建议所有人,
-
Module names − all_lower_case
-
类名和异常名 - 驼峰式
-
全局名称和局部名称 - 全小写
-
函数和方法名称 - 全小写
-
Constants − ALL_UPPER_CASE
这些只是建议,如果你愿意,可以随时更改。但由于大多数开发人员都遵循这些建议,因此你的代码的可读性可能会降低。
Why conform to convention?
我们可以遵循 PEP 建议,因为这允许我们获得,
-
更多开发人员熟悉
-
代码的大多数读者都更清楚。
-
与处理相同代码库的其他贡献者的风格相匹配。
-
专业软件开发人员的标志
-
Everyone will accept you.
Variable Naming − ‘Public’ and ‘Private’
在 Python 中,当我们处理模块和类时,我们将一些变量或属性指定为私有。在 Python 中,不存在“私有”实例变量,除了对象内部以外,无法访问该变量。私有简单地意味着它们根本不是供代码用户使用,而是供内部使用。通常,大多数 Python 开发人员遵循一个惯例,即一个名称以下划线开头,例如。 _attrval(以下示例)应被视为 API 或任何 Python 代码的非公有部分,无论它是一个函数、一个方法还是一个数据成员。以下是我们遵循的命名约定,
-
公有属性或变量(供此模块的导入者或此类的用户使用)− regular_lower_case
-
私有属性或变量(模块或类的内部使用)− _single_leading_underscore
-
不应子类化的私有属性 − __double_leading_underscore
-
Magic 属性 − 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)