Python——魔术方法
特殊属性
创新互联公司专注于噶尔企业网站建设,自适应网站建设,商城网站建设。噶尔网站建设公司,为噶尔等地区提供建站服务。全流程按需定制网站,专业设计,全程项目跟踪,创新互联公司专业和态度为您提供的服务
__name__ 类、函数、方法等的名字
__module__ 类定义所在的模块
__class__ 对象或类所属的类
__bases__ 类的基类的元组,顺序为他们在基类列表中出现的顺序
__doc__ 类、函数的文档字符串,如果没有定义则为None
__mro__ 类的面容,class.mro()返回的结果 保存在__mro__中
__dict__ 类或实例的属性,可写的字典
查看属性
__dir__ 返回类或者对象的所有成员名称列表。dir() 函数就是调用__dir__()。
使用实例调用时,如果提供__dir__(),则返回其返回值,要求是可迭代对象
如果没有提供__dir__(),则会从实例和类及祖先类中手机信息
如果dir([obj]) 参数obj包含方法 __dir__(),该方法将被调用。如果Obj 不包含 __dir__(),该方法将最大限度收集属性信息
dir(obj) 对于不同类型的对象obj具有不同的行为:
1.如果对象是模块对象,返回的列表包含模块的属性名和变量名
2.如果对象是类型或者类对象,返回的列表包含类的属性名,及它的基类的属性名
3.如果obj不写 即dir(),返回列表包含内容不同
- 在模块中,返回模块的属性和变量名
- 在函数中,返回本地作用域的变量名
- 在方法中,返回本地作用域的变量名
dir()测试如下:
classPerson:
defshow(self):
a =100
t=int(a)
print(dir())
deftest(a=50,b=100):
print(dir())
Person().show()
test()
-----------------------------------------------
['a', 'self', 't']
['a', 'b']
魔术方法***
分类:
1.创建、初始化与销毁
__new__ 、__init__ 与__del__
2.hash
3.bool
4.可视化
5.运算符重载
6.容器和大小
7.可调用对象
8.上下文管理
9.反射
10.描述器
11.其它杂项
实例化
__new__方法很少使用,即使创了该方法,也会使用 return super().__new__(cls)基类obj 的 __new__方法来创建实例并返回
classA:
def__new__(cls,*args,**kwargs):
print(cls)
print(*args)
print(**kwargs)
returnsuper().__new__(cls) # 返回cls的实例
# return 1
# return None
def__init__(self,name):
self.name = name
a = A("tom")
print(a)
--------------------------------------------
tom
<__main__.A object at 0x00000281924C46A0>
hash
hash(x) x都一样,求得hash应该不变的,幂等性:一般来说,x不一样,hash应该不一样.
不同的hash算法都有hash冲突的问题,即不同的x求得同样的hash值
hash值相同就会去重吗??
不是的
list 类为为什么不可hash ??
源码中有一句 __hash__ = None, 也就是调用 __hash__() 相当于 None(),一定报错
所有类都继承object,而在这个类是具有 __hash__() 方法的,如果一个类不能被hash,就把__hash__设置为 = None
classA:
def__init__(self,name,age=18):
self.name = name
def__hash__(self):
return1
# def __eq__(self, other):
# return self.name == other.name
def__repr__(self):
returnself.name
print(hash(A("tom")))
print((A('tom'),A('tom')))
print([A('tom'),A('tom')])
print('-------------------------')
s = {A('tom'),A('tom')} # set
print(s)
print({tuple('t'),tuple('t')})
print({('tom',),('tom',)})
print({"tom","tom"})
---------------------------------------------------------------
1
(tom, tom)
[tom, tom]
-------------------------
{tom, tom}# set 没有去重
{('t',)}
{('tom',)}
{'tom'}
__hash__方法只是返回一个hash值作为set 的key,但是去重,还需要__eq__ 来判断两个对象是否相等。
hash值相等,只是hash冲突,不能说明两个对象是相等的。
因此,一般来说提供__hash__方法是为了作set或者dict的key,所以去重,要同时提供__eq__方法
不可hash对象 isinstance(p1, collection.Hashable) 一定为False(import collections)
去重需要提供 __eq__方法
classA:
def__init__(self,name,age=18):
self.name = name
def__hash__(self):
return1
def__eq__(self,other):# 提供了__eq__方法
returnself.name == other.name
def__repr__(self):
returnself.name
print(hash(A("tom")))
print((A('tom'),A('tom')))
print([A('tom'),A('tom')])
print('-------------------------')
s = {A('tom'),A('tom')}
print(s)
print({tuple('t'),tuple('t')})
print({('tom',),('tom',)})
print({"tom","tom"})
------------------------------------------------
1
(tom, tom)
[tom, tom]
-------------------------
{tom}#去重了
{('t',)}
{('tom',)}
{'tom'}
bool
可视化
注意:类型判断要使用type或isinstance, 不能通过判断print输出是否带引号来判断输出值的类型。
classA:
def__init__(self,name,age=18):
self.name = name
self.age = age
def__repr__(self):
return"repr:{},{}".format(self.name,self.age)
def__str__(self):
return"str:{},{}".format(self.name,self.age)
def__bytes__(self):
return"{} is {}".format(self.name,self.age).encode()
print(A('tom'))
print([A('tom')])
print([str(A('tom'))])
print(bytes(A('tom')))
print('str:a,1')
s ='1'
print(s)
s1 ='a'
print(s1)
print([s1],(s,))
print({s,"a"})
-----------------------------------------------------------------
str:tom,18
[repr:tom,18]
['str:tom,18']
b'tom is 18'
str:a,1
1
a
['a'] ('1',)
{'1', 'a'}
运算符重载
operator模块提供以下的特殊方法,可以将类的实例使用下面的操作符来操作
实现A类的2 个实例相减
classA:
def__init__(self,name,age=18):
self.name = name
self.age = age
def__sub__(self,other):
returnself.age - other.age
def__isub__(self,other):
# self.age -= other.age
# return self
# return self.__clas__(self.name, self - other)
returnA(self.name,self- other)
tom = A('tom')
jerry = A('jerry',16)
print(tom - jerry)
print(jerry - tom,jerry.__sub__(tom))
print(id(tom))
tom -= jerry
print(tom.age,id(tom))
-------------------------------------------------------
2
-2 -2
1864834369800
2 1864834369800
__isub__方法定义,一般会in-place来修改自身
如果没有定义 __isub__方法,则会调用__sub__
运算符重载应用场景
往往是用面向对象实现的类,需要做大量的运算,而运算符时这种运算在数学上最常见的表达方式,例如 对 - 进行了运算符重载,实现了类 的二元操作,重新定义为 tom - jerry
@functools.total_ordering装饰器
__lt__, __le__,__eq__,__gt__,__ge__是比较大小必须实现的方法,但是全部写完太麻烦了,,使用@functools.total_ordering装饰器就可以大大简化代码
但是要求__eq__必须实现,其他方法__lt__,__le__,__gt__,__ge__ 实现其中一个
__eq__ 等于可以推断不等于
__gt__ 大于可以推断 小于
__ge__ 大于等于可以推断 小于 等于
也就是用3 个方法,就可以吧所有比较解决了,所以total_ordering可以不使用
classPoint:
def__init__(self,x,y):
self.x = x
self.y = y
def__hash__(self):
returnhash((self.x,self.y))
def__eq__(self,other):
returnselfisotheror(self.x == other.xandself.y == other.y)
def__add__(self,other):
returnPoint(self.x + other.x,self.y + other.y)
def__iadd__(self,other):
self.x,self.y =self.x + other.x,self.y + other.y
returnself
def__eq__(self,other): #判断 == , !=
returnself.x == other.x
def__gt__(self,other): # 判断> , <
returnself.x > other.x
def__ge__(self,other): # 判断>= , <=
returnself.x >= other.x
a = Point(3,2)
b = Point(1,3)
c = Point(3,1)
print(a + b)
print(a > b)
print(a > c)
print(a < b)
print(a < c)
print(a >= c)
print(a <= c)
-----------------------------------------------------------
<__main__.Point object at 0x000001F51ACA49E8>
True
False
False
False
True
True
容器相关方法
为什么空字典,空字符串,空元祖,空列表,空集合可以等效为False
因为 __bool__未定义时,回调用 __len__ 结果为0 等下 False
classA(dict):
def__missing__(self,key):
print('Missingn key:',key)
return0
a = A()
print(a['k'])
------------------------------
Missingn key: k
0
可调用对象
Python 中一切皆对象,函数也不例外
函数即对象,对象foo加上(), 就是调用此函数对象的__call__()方法
deffoo():
print(foo.__module__,foo.__name__)
foo()
# 等价于
foo.__call__()
可调用对象: 定义一个类,并实例化的到其实例,将实例像函数一样调用
classPoint:
def__init__(self,x,y):
self.x = x
self.y = y
def__call__(self,*args,**kwargs):
return"
p = Point(4,5)
print(p)
print(p())
--------------------------------------------------------
<__main__.Point object at 0x000001F7E8E30A20>
classAdder:
def__call__(self,*args):
ret =0
forxinargs:
ret += x
self.ret = ret
returnret
adder = Adder()
print(adder(4,5,6))
print(adder.ret) # 当adder(4,5,6)不存在时,__call__方法不会调用,Adder无adder.ert属性,会抛异常
-------------------------------------------------------
15
15
分享题目:Python——魔术方法
本文链接:http://azwzsj.com/article/pdphjs.html