Python——魔术方法

特殊属性

创新互联公司专注于噶尔企业网站建设,自适应网站建设,商城网站建设。噶尔网站建设公司,为噶尔等地区提供建站服务。全流程按需定制网站,专业设计,全程项目跟踪,创新互联公司专业和态度为您提供的服务

Python——魔术方法

__name__    类、函数、方法等的名字

__module__  类定义所在的模块

__class__   对象或类所属的类

__bases__   类的基类的元组,顺序为他们在基类列表中出现的顺序

__doc__     类、函数的文档字符串,如果没有定义则为None

__mro__     类的面容,class.mro()返回的结果 保存在__mro__中

__dict__    类或实例的属性,可写的字典

查看属性

Python——魔术方法

__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.其它杂项

实例化

Python——魔术方法

__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

Python——魔术方法

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'}

Python——魔术方法

__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

Python——魔术方法

可视化

Python——魔术方法

注意:类型判断要使用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模块提供以下的特殊方法,可以将类的实例使用下面的操作符来操作

Python——魔术方法

实现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

容器相关方法

Python——魔术方法

为什么空字典,空字符串,空元祖,空列表,空集合可以等效为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__()

Python——魔术方法

可调用对象: 定义一个类,并实例化的到其实例,将实例像函数一样调用

classPoint:

   def__init__(self,x,y):

       self.x = x

       self.y = y

   def__call__(self,*args,**kwargs):

       return"".format(self.x,self.y)

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://myzitong.com/article/pdphjs.html