📅  最后修改于: 2021-01-04 04:44:41             🧑  作者: Mango
在本文中,我们将研究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])
[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__()
类也可以从内置类型继承,这意味着可以从任何内置类型继承,并利用那里的所有功能。
在下面的示例中,我们从Dictionary继承,但是随后实现了它的方法__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]))
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!
['a', 'b', 'c']
a
HELLO
在上面的示例中,我们在Mylist中设置了一个三项列表,并隐式调用了__init__方法,当我们打印元素x时,我们获得了三项列表([‘a’,’b’,’c’])。然后,我们将另一个元素添加到此列表。稍后我们要求索引1和索引4。但是,如果您看到输出,我们将从所要求的(index-1)中获取元素。我们知道列表索引从0开始,但是这里索引从1开始(这就是为什么我们得到列表的第一项)。
在本文中,我们将研究将用于变量的名称,尤其是全球Python程序员使用的私有变量和约定。尽管变量被指定为私有,但是在Python并没有设计隐私。像其他任何有据可查的语言一样, Python具有促进的命名和样式约定,尽管它没有强制执行。 Python的创始人“ Guido van Rossum”编写了一个样式指南,该指南描述了名称的最佳做法和用法,被称为PEP8。这是此链接, https:// www。 Python.org / dev / peps / pep-0008 /
PEP代表Python增强建议,是一系列在Python社区中分发以讨论建议的更改的文档。例如,建议所有人,
这些只是建议,您可以根据需要进行更改。但是,由于大多数开发人员都遵循这些建议,所以我的代码可能不太可读。
我们可以遵循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)
setting the "var" attribute
10
no privacy!