Contents
7.16. 一些魔法方法¶
7.16.1. __call__方法¶
eg:
#!/usr/bin/env python
#-*- coding:utf8 -*-
class DistanceFrom(object):
def __init__(self,orage):
self.orage = orage
def __call__(self, x):
return abs(x + self.orage)
number = [1, 2, 3, 4, 5, 6, 7]
hu = DistanceFrom(10)
for i in number:
print(hu(2)+i)
eg:
#!/usr/bin/env python
#-*- coding:utf8 -*-
class Prod:
def __init__(self, data):
self.data = data
def __call__(self, other):
return self.data * other
x = Prod(2)
print(x(3)) #6
print(x(4)) #8
7.16.2. __doc__方法¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
class Func():
"""
这里显示的是描述信息
"""
def func(self):
pass
print(Func.__doc__)
7.16.3. __del__方法¶
析构函数是构造函数的反向函数,析构函数往往用来做“清理善后”的工作,例如数据库链接对象可以在析构函数中释放对象数据库资源的占用,是一个没有返回值和参数的函数。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @auther: 18793
# @Date: 2020/12/15 20:23
# @filename: 03.py
# @Email: 1879324764@qq.com
# @Software: PyCharm
class MyClass(object):
message = "Hello,Developer."
def show(self):
print(self.message)
def __init__(self, name="unset", color="black"):
print("Construcotor is called with param: ", name, " ", color)
def __del__(self):
print("开始清理工作")
if __name__ == '__main__':
inst = MyClass()
inst.show()
inst2 = MyClass("hujianli")
inst2.show()
del inst, inst2
inst3 = MyClass("huxiaojian", "yellow")
inst3.show()
del inst3
7.16.4. __getitem__方法¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
class Company(object):
def __init__(self,employee_list):
self.employee = employee_list
def __getitem__(self, item):
# print(self.employee[item])
return self.employee[item]
company = Company(['11','22','33'])
a = ["derek1","derek2"]
name_set = set()
name_set.add("hujianli1")
name_set.add("hujianli2")
##extend里面可以添加任何可迭代的参数,给类添加一个魔法函数__getitem__,类就变成可迭代的,所以可以extend进去
a.extend(company)
print(a)
a.extend(name_set)
print(a)
7.16.5. __init__方法和__new__方法的区别¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
'''
__new__方法如果不返回对象,不会执行init方法
'''
'''
class User:
def __new__(cls, *args, **kwargs):
print("in new")
def __init__(self,name):
print("in init")
self.name = name
# new是用用来控制对象的生成过程,在对象生成之前
# init是用来完善对象的
# 如果new方法不返回对象,则不会调用init函数
if __name__ == '__main__':
user = User("derek")
'''
class User:
def __new__(cls, *args, **kwargs):
print("in new") #in new
print(cls) #cls是当前class对象 <class '__main__.User'>
print(type(cls)) #<class 'type'>
return super().__new__(cls) #必须返回class对象,才会调用__init__方法
def __init__(self, name):
print("in init") #in init
print(self) #self是class的实例对象 <__main__.User object at 0x00000000021B8780>
print(type(self)) #<class '__main__.User'>
self.name = name
# new是用用来控制对象的生成过程,在对象生成之前
# init是用来完善对象的
# 如果new方法不返回对象,则不会调用init函数
if __name__ == '__main__':
user = User(name="derek")
#总结
# __new__ 用来创建实例,在返回的实例上执行__init__,如果不返回实例那么__init__将不会执行
# __init__ 用来初始化实例,设置属性什么的
7.16.6. __slots__限制实例的变量¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
"""
可以使用__slots__限制实例的变量,比如,只允许Foo的实例添加name和age属性
"""
def print_doc(self):
print("哈哈")
class Foo:
__slots__ = ("name","age")
pass
class AAA(object):
pass
object1 = Foo()
object2 = Foo()
#动态添加实例变量
object1.name = "hujianli"
object2.age = 18
# object.sex = "man"
Foo.show = print_doc
object1.show()
object2.show()
#因为内部有__slots__限制实例的变量
print(Foo.__dict__)
节省内存空间,限制实例只能设置特定的属性,但不限制类来添加动态的属性
class Dog:
__slots__ = ["walk", "walk2", "age", "name"]
def __init__(self, name):
self.name = name
def hujianli(self):
print("预先定义的hujianli方法")
print("【{}】正在慢慢走向你".format(self.name))
d = Dog("Snoopy")
from types import MethodType
# 只允许为实例动态添加walk、age、name这三个属性或方法
d.walk = MethodType(hujianli, d)
d.walk2 = MethodType(lambda self, one_arg: print("这是lambda函数,Dog name is 【{}】 "
"传入参数:{}".format(self.name, one_arg)), d)
d.age = 5
d.walk()
d.walk2("参数测试1")
print()
print()
print("但不限制类来添加动态的属性,使用类来动态定义bar方法,正常输出")
# 但不限制类来添加动态的属性,使用类来动态定义bar方法,正常输出
Dog.bar = MethodType(hujianli, d)
Dog.bar()
# d.foo = 30 # 报错
输出结果:
预先定义的hujianli方法
【Snoopy】正在慢慢走向你
这是lambda函数,Dog name is 【Snoopy】 传入参数:参数测试1
但不限制类来添加动态的属性,使用类来动态定义bar方法,正常输出
预先定义的hujianli方法
【Snoopy】正在慢慢走向你
__slots__属性指定的限制只对当前的类的实例起作用,对子类不起作用。
class GunDog(Dog):
def __init__(self,name):
super(GunDog, self).__init__(name)
pass
hujianli_Class = GunDog("hujianli")
hujianli_Class.speed = 99
print(hujianli_Class.speed)
7.16.7. __str__和__repr__的使用¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
'''
__str__()
__repr__()
'''
class Ppersopn(object):
def __init__(self,name,age,height,weight):
self.name = name
self.age = age
self.height = height
self.weight = weight
def __str__(self):
return "age:{0} name:{1} height:{2} weight:{3}".format(self.name,self.age,self.height,self.weight)
per =Ppersopn("hanmeimei", 18, 170, 60)
print(per)
'''
___str__()调用时使用,是给用户用的,是一个描述对象的方法
__repr__()给机器用的,在python解释器里面直接敲对象名称在
回车后调用的方法,
注意:在没有str时,且有__repe__ str=repr
当一个对象的属性值很多,都需要打印时,
重写了__str__后,简化了代码
'''
eg
#!/usr/bin/env python
# -*- coding:utf8 -*-
# auther; 18793
# Date:2019/5/15 16:02
# filename: repr方法.py
class Apple:
# 实现构造方法
def __init__(self, color, weight):
self.color = color
self.weight = weight
def __repr__(self):
'''
重写__repr__()方法,实现Apple对象的“自我描述”
:return:
'''
return "Apple[color=" + self.color + ", weight=" + str(self.weight) + "]"
if __name__ == '__main__':
hu = Apple("红色", 5.68)
print(hu)
7.16.8. 构造方法和__del__析构方法¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
class Test(object):
def __init__(self):
print("这个是构造函数....")
def __del__(self):
print("这个是析构函数....,结束时自动调用...")
hu = Test()
eg
#!/usr/bin/env python
# -*- coding:utf8 -*-
# auther; 18793
# Date:2019/5/15 16:08
# filename: del 析构方法.py
class Item:
def __init__(self, name, price):
self.name = name
self.price = price
def __del__(self):
print("del删除对象")
if __name__ == '__main__':
im = Item("鼠标", 29.8)
# x = im #如果注释掉这里,将先打印---del删除对象--
#打印im所引用的Item对象
del im
print("------------------------------")
7.16.9. __dir__()方法,列出所有属性和方法¶
#!/usr/bin/env python
# -*- coding:utf8 -*-
# auther; 18793
# Date:2019/5/15 16:14
# filename: __dir__方法.py
"""
查看内置属性和方法和所有定义的属性和方法组成列表。
"""
class Item:
def __init__(self, name, price):
self.name = name
self.price = price
def info(self):
pass
if __name__ == '__main__':
im = Item("鼠标", 29.8)
print(im.__dir__())
print(dir(im))
7.16.10. 运算符重载_add_¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
class Complex(object):
def __init__(self, real, imag=0):
self.real = real
self.imag = imag
def __repr__(self):
return "Complex(%s, %s)" %(self.real,self.imag)
def __str__(self):
return "(%g+%gj)" %(self.real,self.imag)
#self + other
def __add__(self, other):
return Complex(self.real + other, self.imag + other)
#self - other
def __sub__(self, other):
return Complex(self.real - other, self.imag - other)
if __name__ == '__main__':
c = Complex(4, 2)
print(c)
#!/usr/bin/env python
#-*- coding:utf8 -*-
#自定义类实现类的特别的运算方式
class Book:
def __init__(self,name="python入门到精通"):
self.name = name
def __add__(self, other):
#加运算
return self.name + ' add ' + other.name #得到书名相加
def __len__(self):
return len(self.name)
if __name__ == '__main__':
booka = Book()
bookb = Book('Java入门到精通')
print("len(booka):",len(booka))
print("len(bookb):",len(bookb))
print(booka + bookb)
7.16.11. is 判断对象是否属于相同的对象¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
# auther; 18793
# Date:2019/6/10 23:07
# filename: is魔法方法.py
class Person():
def __init__(self):
self.name = "Bob"
bob = Person()
same_bob = bob
print(same_bob is bob)
other_bob = Person()
print(other_bob is bob)
7.16.12. 其他一些魔法方法¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
'''
和比较相关的魔术方法
__eq__(self, other) self == other
__ne__(self, other) self != other
__lt__(self, other) self < other
__gt__(self, other) self > other
__le__(self, other) self <= other
__ge__(self, other) self >= other
和数学相关的魔术方法
__add__(self, other) self + other
__sub__(self, other) self - other
__mul__(self, other) self * other
__floordiv__(self, other) self // other
__truediv__(self, other) self / other
__mod__(self, other) self % other
__pow__(self, other) self ** other
'''
class Word():
def __init__(self,text):
self.text = text
# def __eq__(self, other):
# if self.text.lower() == other.lower():
# print("True")
# else:
# print("False")
def __add__(self, other):
if isinstance(self.text, int):
return self.text + other
else:
return False
# def __str__(self):
# return self.text
def __repr__(self):
return 'Word("self.text")'
first = Word(10)
first.__eq__(10)
print(first)
add = first.__add__(20)
print(add)
eg
#!/usr/bin/env python
# -*- coding:utf8 -*-
# auther; 18793
# Date:2019/6/15 14:40
# filename: 比较运算符.py
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
# 定义setSize()函数
def setSize(self, size):
self.width, self.height = size
# 定义getSize()函数
def getSize(self):
return self.width, self.height
# 使用property定义属性
size = property(getSize, setSize)
# 定义gt方法
def __gt__(self, other):
# 判断是否是Rectangle
if not isinstance(other, Rectangle):
raise TypeError(">比较要求目标是Rectangle")
return True if self.width * self.height > other.width * other.height else False
# 定义eq方法
def __eq__(self, other):
# 判断是否是Rectangle
if not isinstance(other, Rectangle):
raise TypeError("==比较要求目标是Rectangle")
return True if self.width * self.height == other.width * other.height else False
# 定义ge方法
def __ge__(self, other):
# 判断是否是Rectangle
if not isinstance(other, Rectangle):
raise TypeError(">=比较要求目标是Rectangle")
return True if self.width * self.height >= other.width * other.height else False
def __repr__(self):
return "Rectangle(width={},height={})".format(self.width, self.height)
r1 = Rectangle(4, 5)
r2 = Rectangle(3, 4)
print(r1 > r2)
print(r1 == r2)
print(r1 >= r2)
print(r1 != r2)
r3 = Rectangle(2, 6)
print(r2 > r3)
print(r2 == r3)
print(r2 >= r3)
print(r2 != r3)
print(r1)
print(r2)
print(r3)
输出信息
True
False
True
True
False
True
True
False
Rectangle(width=4,height=5)
Rectangle(width=3,height=4)
Rectangle(width=2,height=6)
7.16.13. __getattr__和__getattribute__的区别¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
'''
object.__getattr__(self, name)
找不到attribute的时候,会调用getattr,返回一个值或AttributeError异常。
object.__getattribute__(self, name)
无条件被调用,通过实例访问属性。如果class中定义了__getattr__(),则__getattr__()不会被调用(除非显示调用或引发AttributeError异常)
'''
class User:
def __init__(self, info={}):
self.info = info
#__getattr__是在查找不到属性的时候调用
def __getattr__(self, item):
return self.info[item]
#__getattribute不管属性存不存在,都访问这个
def __getattribute__(self, item):
return "zhang_derek"
if __name__ == '__main__':
user = User(info={"name":"derek","age":24})
#不管属性存不存在,都走__getattribute__
print(user.name) #zhang_derek #即使属性存在也走__getattribute__
print(user.test) #zhang_derek #不存在的属性也能打印
print(user.company) #zhang_derek #不存在的属性也能打印
7.16.14. __setattr__、__getattr、__getattribute、__delattr__ 方法¶
__setattr__(self,name,value):如果要给name赋值,就调用这个方法。
__getattr__(self,name):如果name被访问,同时它不存在,此方法被调用。
__getattribute__(self,name):当name被访问时自动被调用(注意:这个仅能用于新式类),无论name是否存在,都要被调用。
__delattr__(self,name):如果要删除name,这个方法就被调用。
#!/usr/bin/env python
#-*- coding:utf8 -*-
class Bird(object):
feather = True
class chicken(Bird):
fly = False
def __init__(self,age):
self.age = age
def __getattr__(self, item):
if item == "hujianli":
if self.age > 1.0:
return True
else:
return False
else:
return AttributeError(item)
if __name__ == '__main__':
hu = chicken(10)
print(hu.hujianli) #True
hu.age = 0.2
print(hu.hujianli) #False
print(hu.jian)
eg
#!/usr/bin/env python
# -*- coding:utf8 -*-
# auther; 18793
# Date:2019/6/15 2:54
# filename: getattr和setattr.py
class Rectangle:
def __init__(self, name, age):
self.name = name
self.age = age
def __setattr__(self, key, value):
# print("--------设置{}属性-----".format(key))
if key == "name":
if 2 < len(value) <= 8 or len(value) > 8:
self.__dict__["name"] = value
else:
raise ValueError("name 的长度必须在2~8之间")
elif key == "age":
if 10 < value < 60:
self.__dict__["age"] = value
else:
raise ValueError("age必须在10~60之间")
if __name__ == '__main__':
hu = Rectangle("huajianli", 20)
print(hu.name)
print(hu.age)
hu.age = 12
hu.name = "huj"
print(hu.name)
# hu.age = 2 #报错