特点或者作用:
class 类名(父类名):
方法
属性
子类名.__base__
:显示类的父类子类名.__bases__
:显示类的父类元组子类名.__mro__
:显示方法查找的顺序,父类的元组子类名.mro()
:同上父类名.__subclasses__()
:显示类的子类列表class FatherObject:
#父类的初始化函数
def __init__(self,number_people,name):
self.number_people = number_people
self.name = name
def people_eat(self,a):
print("我喜欢吃{0}菜".format(a))
def people_drink(self,a):
print('我喜欢喝{0}'.format(a))
def people_live(self,a):
print('我喜欢住在{0}'.format(a))
@staticmethod
def people_travel(a):
print('我喜欢{0}出门'.format(a))
class SonObject(FatherObject):#继承父类
@staticmethod
def people_play(a):
print('我喜欢去{0}玩儿'.format(a))
def people_study(self,a):
print('我的名字是{0},一家{1}口人'.format(
self.name,self.number_people))
# format括号中的信息是父类的初始化属性,子类中没有初始化
print('我想通过{0}的方式学习'.format(a))
@staticmethod
def people_live(a,b):
print('我住在{0},离{1}很近'.format(a,b))
print("查看类的父类信息:",SonObject.__base__)
print("查看类的父类的元组:",SonObject.__bases__)
print("显示方法的查找顺序:",SonObject.__mro__)
print("显示方法的查找顺序:",SonObject.mro())
print("类的子类列表:",FatherObject.__subclasses__())
print("=========创建子类实例和调用属性=======")
cla = SonObject('4','jjj')# 因为父类存在初始化,必须传入参数
cla.people_study('不断练习')
#继承属性值后,对象方法必须传入属性值,拓展调用新函数
print("========对象和类名,调用父类静态方法====")
SonObject.people_travel('坐飞机')
cla.people_travel('坐轮船')
print("======对象调用父类的对象方法======")
cla.people_drink("奶茶")
print("=======类名和对象,调用子类的静态方法======")
SonObject.people_play('海边')
cla.people_play('沙漠')
print("======方法重写,名称一致,调用的是子类的新方法=========")
SonObject.people_live('深圳','海边')
*****************run_result****************
查看类的父类信息: <class '__main__.FatherObject'>
查看类的父类的元组: (<class '__main__.FatherObject'>,)
显示方法的查找顺序: (<class '__main__.SonObject'>, <class '__main__.FatherObject'>, <class 'object'>)
显示方法的查找顺序: [<class '__main__.SonObject'>, <class '__main__.FatherObject'>, <class 'object'>]
类的子类列表: [<class '__main__.SonObject'>]
=========创建子类实例和调用属性=======
我的名字是jjj,一家4口人
我想通过不断练习的方式学习
========对象和类名,调用父类静态方法====
我喜欢坐飞机出门
我喜欢坐轮船出门
======对象调用父类的对象方法======
我喜欢喝奶茶
=======类名和对象,调用子类的静态方法======
我喜欢去海边玩儿
我喜欢去沙漠玩儿
======方法重写,名称一致,调用的是子类的新方法=========
我住在深圳,离海边很近
__dict__
中__dict__
——>类__dict__
,如果有继承,还要查询父类的__dict__
super(子类名,self).父类的方法名()
,也可以省略super括号中的参数class FatherObject:
#父类的初始化函数
def __init__(self,number_people,name):
self.number_people = number_people
self.name = name
def people_eat(self,a):
print("我喜欢吃{0}".format(a))
def people_basic(self):
print("我的名字是{1},家里有{0}口人".format(self.name,self.number_people))
class SonObject(FatherObject):#继承父类
def people_eat(self,a,*args):
self.people_basic()#继承
print('我也喜欢吃{0}'.format(a))
super(SonObject,self).people_eat(args)#超继承
super().people_eat(args)#可以省略括号中的参数
print("========实例化===========")
cla = SonObject('gbk','18')
cla.people_eat('北京菜','川菜','粤菜','鲁菜','豫菜')
#继承调用父类的方法
*************run_result**********
========实例化===========
我的名字是gbk,家里有18口人
我也喜欢吃北京菜
我喜欢吃('川菜', '粤菜', '鲁菜', '豫菜')
我喜欢吃('川菜', '粤菜', '鲁菜', '豫菜')
class FatherObject:
#父类的初始化函数
def __init__(self,number_people,name):
self.number_people = number_people
self.name = name
def people_eat(self,a):
print("我喜欢吃{0}".format(a))
def people_basic(self):
print("我的名字是{1},家里有{0}口人".format(self.name,self.number_people))
class SonObject(FatherObject):#继承父类
def __init__(self,k,v,item):
FatherObject.__init__(self,k,v)# 继承了父类中的初始化函数
self.item = item
# 也可以使用super方式写,不过init中不要传self
# def __init__(self,k,v,item):
# super().__init__(k,v)# 继承了父类中的初始化函数
# self.item = item
def people_eat(self,*args):
self.people_basic()#继承
print('我也喜欢吃{0}'.format(self.item))
super(SonObject,self).people_eat(args)#超继承
super().people_eat(args)#可以省略括号中的参数
print("========实例化===========")
cla = SonObject('gbk','18','北京菜')
cla.people_eat('川菜','粤菜','鲁菜','豫菜')
#继承调用父类的方法
************run_result***********
========实例化===========
我的名字是gbk,家里有18口人
我也喜欢吃北京菜
我喜欢吃('川菜', '粤菜', '鲁菜', '豫菜')
我喜欢吃('川菜', '粤菜', '鲁菜', '豫菜')
class ClassName(父类列表):
类体
class FatherObject:
#父类的初始化函数
def __init__(self,number_people,name):
self.number_people = number_people
self.name = name
def people_eat(self,a):
print("我喜欢吃{0}".format(a))
def people_basic(self):
print("我的名字是{1},家里有{0}口人".format(self.name,self.number_people))
class SonObject(FatherObject):#继承父类
def __init__(self,k,v,item):
super().__init__(k,v)# 继承了父类中的初始化函数
self.item = item
def people_eat(self,*args):
self.people_basic()#继承
print('我也喜欢吃{0}'.format(self.item))
super(SonObject,self).people_eat(args)#超继承
super().people_eat(args)#可以省略括号中的参数
print(SonObject.mro())
***************run_result************
[<class '__main__.SonObject'>, <class '__main__.FatherObject'>, <class 'object'>]
1.人和机器猜拳游戏写成一个类,有如下几个函数:
class PeopleVmCom:
def select_ppeople(self):
people = int(input("请选择角色:1 曹操 2张飞 3 刘备"))
dict_people = {1:'曹操', 2:'张飞', 3:'刘备'}
try:
people_role = dict_people[people]
except Exception :
print('您选择的角色不存在,默认指定角色刘备')
people_role = '刘备'
print("您选择的角色是{0}".format(people_role))
return people
def people_result(self):
people_result = int(input('请出拳(数字):1剪刀 2石头 3布'))
dict_result = {1:'剪刀', 2:'石头', 3:'布'}
try:
people_role = dict_result[people_result]
print("您选择的角色是{0}".format(people_role))
except Exception :
print('您选择的角色不存在,默认指定角色剪刀')
people_result = 2
print("您选择的角色是{0}".format(dict_result[people_result]))
return people_result
def computer_result(self):
import random
dict_role = {1:'剪刀', 2:'石头', 3:'布'}
computer_result = random.randint(1,3)
print("电脑输出的数字是{0}".format(dict_role[computer_result]))
return computer_result
def vs_result(self):
people = self.select_ppeople()
people_result = self.people_result()
computer_result = self.computer_result()
if people_result == 2 and computer_result ==1:
result = '角色赢啦!'
print(result)
elif people_result == 1 and computer_result ==3:
result = '角色赢啦!'
print(result)
elif people_result == 3 and computer_result ==2:
result = '角色赢啦!'
print(result)
elif people_result == computer_result :
result = '平局'
print(result)
else:
result = '很抱歉,电脑赢啦!'
print(result)
return result
def count_result(self):
count_ping = 0
couunt_computer = 0
count_people = 0
while 1:
result =self.vs_result()
if result == '平局':
count_ping += 1
elif result == '很抱歉,电脑赢啦!':
couunt_computer += 1
else:
count_people +=1
mes = input('是否继续?y 继续 n 终止')
if mes == 'y':
continue
else:
print('电脑胜利{0}轮,您胜利{1}轮,平局{2}轮'.format(couunt_computer,count_people,count_ping))
break
PeopleVmCom().count_result()
2.按照以下要求定义一个游乐园门票类,并创建实例调用函数,完成儿童和大人的总票价统计(人数不定,由你输入的人数个数来决定)
class TicketPrice:
def __init__(self):
self.people_ticket = 100
self.child_ticket = 50
def ticket_price(self):
child_num = int(input('请输入小孩人数:'))
people_num = int(input('请输入大人人数:'))
today_datetime = int(input('请输入今天(1-7代表周一到周日):'))
if today_datetime in range(1,6):
people_money = self.people_ticket * people_num
child_money = self.child_ticket * child_num
total_money = people_money + child_money
else:
people_money = self.people_ticket * people_num
child_money = self.child_ticket * child_num
total_money = (people_money + child_money) * 1.2
print('儿童花费{}元,大人花费{}元,总计{}元'.format(child_money, people_money, total_money))
3.Shape父类,要求所有子类都必须提供面积计算,子类有三角形,圆形和矩形
import math
class Shape:
@property
def area(self):
raise NotImplementedError("父类未实现")
# 父类中定义了area属性,子类可以继承
# 子类中调用area属性,area未实现,就不会覆盖父类的area
# 继承之后,子类调用未被覆盖的area,就会抛出属性错误的异常
# 因为父类的area,在没有被覆盖之前,写的就是直接抛出异常
# 常见写法:
# 在父类中定义一个统一的属性方法,子类可以继承
# 防止子类直接调用父类的属性的方式是:方法直接抛出异常,属性直接给None
# 三角形
class Triangle(Shape):
def __init__(self,a,b,c):
self.a = a
self.b = b
self.c = c
@property
def area(self):
p = (self.a + self.b +self.c)/2
return math.sqrt(p*(p-self.a)*(p-self.b)*(p-self.c))
# 长方形
class Rectangle(Shape):
def __init__(self,width,heigth):
self.width = width
self.heigth = heigth
@property
def area(self):
return self.width*self.heigth
# 圆
class Circle(Shape):
def __init__(self,radius):
self.d = radius*2
@property
def area(self):
return math.pi * self.d *self.d *0.25
shapes = [Triangle(3,4,5),Rectangle(3,4),Circle(4)]
for s in shapes:
print("The area of {} = {}".format(s.__class__.__name__,s.area))
print(s.__dict__)
print(Shape.__dict__)
*************run_result*********************
The area of Triangle = 6.0
{'a': 3, 'b': 4, 'c': 5}
The area of Rectangle = 12
{'width': 3, 'heigth': 4}
The area of Circle = 50.26548245743669
{'d': 8}
{'__module__': '__main__',
'area': <property object at 0x0000023A4E073E00>,
'__dict__': <attribute '__dict__' of 'Shape' objects>,
'__weakref__': <attribute '__weakref__' of 'Shape' objects>,
'__doc__': None}
__init__
函数和__del__
函数就是魔术方法,他们对应类的创建于销毁__new__
__init__
方法之前执行class Myclass:
def __init__(self,name):
self.name = name # 如果new方法没有return,这个方法不会执行
def __new__(cls, *args, **kwargs):
print("这一个new方法")
# return super().__new__(cls) # 使用super调用父类的方法
return object.__new__(cls)# 使用父类的名称调用
def print_g(self):
print(self.name)
a = Myclass("yiyi")
a.print_g()
# 如果类属性__insatance 为None,
# 那怎么就创建一个对象,并赋值为这个对象的引用,
# 保证下次调用这个方法时能够知道之前已经创建过对象了,
# 这样就保证了只有一个对象
class Test():
__instance = None
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = super().__new__(cls)
return cls.__instance
return cls.__instance
a= Test()
a.name = "yiyi"
b= Test()
print(b.name) # a创建的属性,b实例可以访问
************run_result***********
yiyi
__hash__
、__eq__
__hash__()
方法的,如果一个类不能被hash,就是重写了__hash__
方法,并将其返回值设置成了None__hash__
方法,没有提供的话,isinstance(类名/对象, collections.Hashable)
的结果肯定是falsecollections.Hashable
,则要导入模块,语句:from collections import Hashable
class A:
X = 1234
def __init__(self):
self.a = 5
self.b = 6
def __hash__(self):
return 1
print("求hash值,返回的是A类中自定义的hash:",hash(A()))
print((A(),A()))
s = {A(),A()}
print("==没有去重的原因:hash的两个值并不相等,解决方式,使用eq方法==")
print(s)
*********** run_result**************
求hash值,返回的是A类中自定义的hash: 1
(<__main__.A object at 0x100dfb910>, <__main__.A object at 0x100dfb8b0>)
==没有去重的原因:hash的两个值并不相等,解决方式,使用eq方法==
{<__main__.A object at 0x100dfb910>, <__main__.A object at 0x100dfb8b0>}
# 解决方式:
class A:
X = 1234
def __init__(self):
self.a = 5
self.b = 6
def __hash__(self):
return 1
def __eq__(self, other):
return True # 使用eq函数,默认函数中的属性相等
# return self.a == self.b 这里的==用的是object中的eq方法,
# 而不是A类中自定义的方法
print("求hash值,返回的是A类中自定义的hash:",hash(A()))
print((A(),A()))
s = {A(),A()}
print("==使用eq函数,默认属性相等,返回True,set去重成功==")
print(s)
**************run_result*************
求hash值,返回的是A类中自定义的hash: 1
(<__main__.A object at 0x10522ba30>, <__main__.A object at 0x10522b9d0>)
==使用eq函数,默认属性相等,返回True,set去重成功==
{<__main__.A object at 0x10522ba30>}
__bool__()
,就找__len__()
返回长度,非0位为真__len__()
也没有定义,那么所有的示例都返回为真class Point:
'''bool和len方法都不存在,所有调用返回为真'''
def __init__(self,x,y):
self.x = x
self.y = y
def __eq__(self, other):
if self is other:
return True
return self.x == other.x and self.y == other.y
def __len__(self):# 没有bool,看这个方法,大于0为True
return 0
#return False
def __bool__(self):# 优先看这个方法,返回结果为True
return True
print(bool(Point(4,5)))
方法 | 意义 |
---|---|
__repr__ |
内建函数repr() 对一个对象获取字符串表达如果一个类定义了 __repr__() ,但是没有定义__str__ 那么在请求该类的实例的非正式的字符串表示时也将调用 __repr__() |
__str__ |
str()函数、内建函数format、print()函数调用,需要返回对象的字符串表达 |
__bytes__ |
bytes的时候,返回一个对象的bytes表达,即返回bytes()对象 |
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
def __eq__(self, other):
if self is other:
return True
return self.x == other.x and self.y == other.y
def __repr__(self):
return "答案:{0}".format("abc")
def __str__(self):
return str(123)
P = Point(4,5)
p = Point(3,4)
# 直接作用于对象,强行调用对象的__str__方法
print("单个打印:",P)
k = [P,p]
for _ in k:
print("循环列表元素:",_)#_为列表中的元素,也是字符串
# 如果print的对象不是字符串类型,
# 打印的时候,调用的是__repr__方法
print("列表打印:",k)
***********run_result**************
单个打印: 123
循环列表元素: 123
循环列表元素: 123
列表打印: [答案:abc, 答案:abc]
运算符 | 特殊方法 | 含义 |
---|---|---|
< 、<= 、== 、> 、>= 、!= |
__lt__ 、__le__ 、 __eq__ 、__gt__ 、 __ge__ 、 __ne__ |
比较运算符 |
+ 、- 、* 、/ 、% 、// 、divmod |
__add__ 、__sub__ 、__mul__ 、__truediv__ 、__mod__ 、__floordiv__ 、__pow__ 、__divmod__ |
算数运算符,移位或者(#`O′)运算也有相应的方法 |
+= 、-= 、*= 、/= 、%= 、//= 、++= |
__iadd__ 、__isub__ 、__imul__ 、__itruediv__ 、__imod__ 、__ifloordiv__ 、__ipow__ |
class A :
def __init__(self,x):
self.x = x
# 减法,other是个对象(实例)
def __sub__(self, other):
return self.x - other.x
#加法
def __add__(self, other):
return self.x + other.x
def __lt__(self, other):
return self.x <= other.x
def __ne__(self, other):
return self.x != other.x
def __eq__(self, other):
return self.x == other.x
def __iadd__(self, other):
self.x += other.x
return self # 这里,如果直接返回self,则是对数据就地修改
#否则就是返回新的对象
def __repr__(self): # 存在这个方法的情况下,返回的就不是地址
# 这个方法自动执行,不需要调用
return str(self.x)
a = A(4)
b = A(10)
print(a-b)
print(a.__sub__(b))
print(a+b)
print(a.__add__(b))
lst = [a,b]
print(list(sorted(lst)))
# 如果存在大于等于,就可以对对象进行排序
print(a==b)
print(a.__eq__(b))
print(a!=b)
print(a.__ne__(b))
a+=b
print(a)
class Point:
# 初始化一个点,有x和y两个元素组成
def __init__(self,x,y):
self.x = x
self.y = y
# 判断设置的实例,是不是一个点
def __eq__(self, other):
if self is other:
return True
return self.x == other.x and self.y == other.y
# 实现实例的加法
def __add__(self, other):
add_x = self.x + other.y
add_y = self.y + other.y
return (add_x,add_y)
def add(self,other):
return Point(other.x+self.x,other.y+self.y)
# 返回的是一个对象,可以在后面直接添加数值
def __repr__(self):
return "Point:{},{}".format(self.x,self.y)
P = Point(11,12)
p = Point(10,11)
point = (P,p)
print("打印两个实例的元祖:",point)
print("add方法的调用:",point[0].add(point[1]))# add方法,返回的是一个对象
print("元祖中的两个点相加",point[0]+point[1])
print("两个向量的和:",p+P)
print("构建实例之后,解构:",Point(*(point[0]+point[1])))
print("是不是一个点:",p==P)
__len__
:内建函数len(),返回对象的长度(>=0的整数)__bool__()
方法,会看__len__()
方法是否存在,存在返回非0 的数值__iter__
:迭代容器时,钓鱼哦那个,返回一个新的迭代器对象__contains__
:in成员运算符,没有实现就调用__iter__()
方法遍历__getitem__
:实现self[key]访问__setitem__
:和__getitem__
的访问类似,是设置值的方法__missing__
:字典使用__getitem__()
调用的时候,key不存在执行该方法class Item:
def __init__(self,name,**kwargs):
self.name = name
self._spec = kwargs # 字典
self.data_d = {self.name:self._spec}
def __repr__(self):
return "{}:{}".format(self.name,self._spec.values())
class Cart(Item):
def __init__(self,name,**kwargs):
super().__init__(name,**kwargs)
self.iterms = []#进来就是空的购物车
# 重写时设置长度方法,否则不能对实例求长度
def __len__(self):
return len(self.iterms)
# 在购物车中添加商品,是否需要返回值,根据业务的实际情况设置
def additem(self,item):
self.iterms.append(item)
#这个方法解决持续添加商品的问题
# others可以不是实例,可以是任何类型的数据
# 不过既然是购物车,要加入的东西就是商品的信息
def __add__(self, other):
if isinstance(other,Item) or isinstance(other,dict):
self.iterms.append(other)
return self
def __getitem__(self, index):
return self.iterms[index]
def __setitem__(self, key, value):
print(key,value)
self.iterms[key] = value
def __iter__(self):
return iter(self.iterms)
def __repr__(self):
return str(self.iterms)
def __missing__(self, key):
# 特指dict或者setkey不存在的时候,生效
return key
a = Cart("電子產品")
print("添加前:",len(a))
print("*********商品实例化************")
good_1 = Item("电脑",id = "001")
good_2 = Item("手机",id = "002")
good_3 = Item("食品",id = "003")
good_4 = Item("玩具",id = "004")
good_5 = Item("汽车",id = "005")
good_6 = Item("房产", id = "006")
#这里可以使用,自动调用的是__add__ 方法,因为返回的是self对象
#所以可以在后面直接添加方法,即:
# 等价于:cart.__add__(good_3).__add__(good_2)
print("************连续调用__add__添加商品**********")
print(a+good_3+good_5+good_4+good_1+good_2)
print("************调用additem单个添加商品**********")
a.additem(good_6)
print(a.iterms)
print("添加后:",len(a))
print("*************存在__iter__,可以对实例进行遍历************")
for x in a:
print(x)
# 存在__getitem__和__setitem__,可以直接对实例进行索引赋值和取值
good_7 = Item("纸巾", id = "001")
print("修改前取值:",a[3])
a[3] = good_7
print("修改后取值:",a[3])
good_8 = Item("键盘",id = "009")
a + good_8.data_d
print("************确认missing是否生效********")
print(a[6]["火箭"])
**************************run_result********************
添加前: 0
************连续调用__add__添加商品**********
[食品:dict_values(['003']), 汽车:dict_values(['005']),
玩具:dict_values(['004']), 电脑:dict_values(['001']),
手机:dict_values(['002'])]
************调用additem单个添加商品**********
[食品:dict_values(['003']), 汽车:dict_values(['005']),
玩具:dict_values(['004']), 电脑:dict_values(['001']),
手机:dict_values(['002']), 房产:dict_values(['006'])]
添加后: 6
*************存在__iter__,可以对实例进行遍历************
食品:dict_values(['003'])
汽车:dict_values(['005'])
玩具:dict_values(['004'])
电脑:dict_values(['001'])
手机:dict_values(['002'])
房产:dict_values(['006'])
修改前取值: 电脑:dict_values(['001'])
3 纸巾:dict_values(['001'])
修改后取值: 纸巾:dict_values(['001'])
**********修改后的iterms**********
[食品:dict_values(['003']), 汽车:dict_values(['005']),
玩具:dict_values(['004']), 纸巾:dict_values(['001']),
手机:dict_values(['002']), 房产:dict_values(['006'])]
************确认missing是否生效********
没有报错,就生效了
#函数
def foo():
print(foo.__module__,foo.__name__)
foo()# 等价于下面的代码
foo.__call__()
__call__()
__call__
__call__
:类的第一个方法,实例就可以像函数一样调用class Point:
def __init__(self,x,y):
self.x = x
self.y = y
def __call__(self, *args, **kwargs):
return "Point({0},{1})".format(self.x,self.y)
p = Point(4,5)
print(p) # p表示一个实例
print(p())#p() ,表示p.__call__()
print(p.__call__())
#类的封装
class Adder:
def __call__(self, *args, **kwargs):
ret = 0
print(*args)# 非=的数据,全部由args接收,放在一个迭代器中
for x in args:#遍历相加
ret +=x
self.ret = ret#给adder添加ret的属性
return ret # 返回
adder = Adder()# 创建实例
print(adder(1,2,3,4,5,6,7,8,9,10))
print(adder.ret)
print(adder.__dict__)
class Fib:
def __init__(self):
self.lst = [0,1,1]
def __call__(self, x):
if x <len(self.lst):
return self.lst
for i in range(2,x):
self.lst.append((self.lst[i-1]+self.lst[i]))
return self.lst
f = Fib()
print(f(60))
# 打印斐波那契数列中,第n项的值
class Fib:
def __init__(self):
self.lst = [0,1,1]
def __call__(self, index):
if index < 0:
return IndexError("Error")
if index <len(self.lst):
return self.lst[index]
for i in range(3,index+1):
self.lst.append((self.lst[i-1]+self.lst[i-2]))
return self.lst[index]
def __iter__(self):
return iter(self.lst)
def __len__(self):
return len(self.lst)
def __str__(self):
return str(self.lst)
f = Fib()
print(f(60),len(f))
for x in f:
print(x)
__enter__()
和__exit__()
方法,他就属于上下文管理的对象__enter__
,进入对象相关的上下文__exit__
,退出与此对象相关的上下文,返回值为正数或者True,可以不抛出异常(压制异常),返回值为0或者False,会抛出异常__enter__
方法没有其他参数__exit__
方法有三个参数,分别是:exc_type, exc_val, exc_tb
,这三个参数都和异常有关,抛出异常的后会打印相关的信息,无异常都返回Noneexc_type
是异常的类型exc_val
是异常的值exc_tb
是异常的追踪信息class Point:
def __init__(self):
print("初始化:int")
def __enter__(self):
print("打开文本:enter")
def __exit__(self, exc_type, exc_val, exc_tb):
print("关闭:exit")
p = Point()
with p as f:
#sys.exit() # 在这里6添加结束运行的语句之后,下面的就不执行了
print("执行代码:do")
print("比较:",p==f,p)
# 因为是将enter的返回值给f,其返回值为None,所以f就是None
print("result:",p is f,f)
************run_result***********
初始化:int
打开文本:enter
执行代码:do
比较: False <__main__.Point object at 0x102860d30>
result: False None
关闭:exit
sys.exit()
,他就会退出当前解释器,python运行环境就自动退出class MyFile(object):
def __init__(self,file_name,open_method):
self.name = file_name
self.method = open_method
def __enter__(self):
self.f = open(self.name,self.method)
return self.f
def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()
with MyFile("user.txt","r") as f:
content = f.read()
print(content)
*********************run——result************
{"user":"python12","pwd":"python","token":True}
import time
import datetime
from functools import wraps
def timeir(fn):
@wraps(fn) #等价于wraps(fn)(wrapper)
# 或者理解为a = wraps(fn); a(wrapper)
def wrapper(*args,**kwargs):
start = datetime.datetime.now()
ret = fn(*args,**kwargs)
delta = (datetime.datetime.now()-start).total_seconds()
print("dec {} took {}s".format(fn.__name__,delta))
return ret
return wrapper
class TimeIt:
def __init__(self,fn):
self._fn = fn
def __enter__(self):
print("enter")
self.start = datetime.datetime.now()
return self # 返回对象本身,在上下文管理中,可以调用类中的方法
def __exit__(self, exc_type, exc_val, exc_tb):
print("exit")
data = (datetime.datetime.now() - self.start).total_seconds()
# 此方法是最后执行的一个方法,时间直接在这个方法中计算比较好
print("context {} took {}s".format(self._fn.__name__,data))
return True # 解决异常情况的抛出,如果为False,就会抛出
def print_d(self):
print("end")
#函数
@timeir
def add(x,y):
time.sleep(5)
return x+y
with TimeIt(add) as f:
k = add(5,6)
print("add`s result:",k)
f.print_d()
# f接受TimeIt()在enter中的返回值,就相当于TimeIt()
import time
import datetime
from functools import wraps
def timeir(fn):
@wraps(fn)
def wrapper(*args,**kwargs):
start = datetime.datetime.now()
ret = fn(*args,**kwargs)
delta = (datetime.datetime.now()-start).total_seconds()
print("dec {} took {}s".format(fn.__name__,delta))
return ret
return wrapper
class TimeIt:
def __init__(self,fn):
self._fn = fn
def __enter__(self):
print("enter")
self.start = datetime.datetime.now()
print(self._fn,self)
return self # 返回对象本身,在上下文管理中,可以调用类中的方法
#添加可调用函数
def __call__(self, *args, **kwargs):
return self._fn(*args,**kwargs)
def __exit__(self, exc_type, exc_val, exc_tb):
print("exit")
data = (datetime.datetime.now() - self.start).total_seconds()
# 此方法是最后执行的一个方法,时间直接在这个方法中计算比较好
print("context {} took {}s".format(self._fn.__name__,data))
return True # 解决异常情况的抛出,如果为False,就会抛出
def print_d(self):
print("end")
#函数
@timeir
def add(x,y):
time.sleep(5)
return x+y
with TimeIt(add) as f:
print(f(5,6))
k = add(5,6)
print("add`s result:",k)
f.print_d()
print(f)
# f接受TimeIt()在enter中的返回值,就相当于TimeIt()
# 可直接调用类中的方法
__call__
方法import time
import datetime
from functools import wraps
class TimeIt:
def __init__(self,fn):
self._fn = fn
wraps(fn)(self) # 这里,其实是用wraps将类的属性全部添加到实例的__dict__中
#这样就可以调用doc和name属性
def __call__(self, *args, **kwargs):
print("__call__")
start = datetime.datetime.now()
ret = self._fn(*args,**kwargs)
data = (datetime.datetime.now()-start).total_seconds()
print("dec {} took {}s".format(self._fn.__name__,data))
return ret
#函数
@TimeIt #等价于TimeIt(add)
def add(x,y):
'''this is add def'''
time.sleep(5)
return x+y
print(add(5,6))
print("装饰器,装饰后的函数,实际上是实例:",add)
print("doc:{0},name:{1}".format(add.__doc__,add.__name__))
***********************run_result*************************
__call__
dec add took 5.013974s
11
装饰器,装饰后的函数,实际上是实例: <__main__.TimeIt object at 0x00000225947A3FD0>
doc:this is add def,name:add
__enter__
中做处理__enter__
和__exit__
之后再__enter__()
和__exit__()
比较方便import contextlib
import datetime
import time
@contextlib.contextmanager
def add(x,y): # 为生成器增加了上下文管理
start = datetime.datetime.now()
try:
yield x+y
#yield的值只能有一个,作为__enter__()方法的返回值
finally:
delta = (datetime.datetime.now()-start).total_seconds()
print("run time:{0}".format(delta))
with add(5,6) as a:
time.sleep(3)
print(a)
************run_result***********
11
run time:3.005129
__lt__
等比较方法全部写完比较麻烦,因此使用这个装饰器简化代码from functools import total_ordering
@total_ordering
class Order:
def __init__(self,x):
self.x = x
def __lt__(self, other):
return self.x < other.x # 比较方法至少实现一个
def __eq__(self, other): # eq方法必须实现
return self.x == other.x
O= Order(5)
o= Order(6)
print(O >= o)
print(O <= o)
print(O==o)
type() 、is instance()、callable()、dir()、getattr()
class Dispatcher:
pass
class Dispatcher:
#命令和函数存储的地方
# 解决函数注册的问题,直接将函数名和对应的函数写入字典
def run_def(self,cmd,fn):
if isinstance(cmd,str):
setattr(self.__class__,cmd,fn)
else:
print("error")
#缺省函数,不知道的函数,返回不知道
def default_def(self):
print("Unknown comnmand")
#调度函数
def dispatcher(self):
while True:
cmd = input(">>")
if cmd.strip() == "quit":
return
# print(command,cmd)
getattr(self,cmd.strip(),self.default_def)()
#self.command.get(cmd,self.default_def)()
#command是一个字典,cmd存在,就去执行fn,cmd不存在,执行默认函数default_def
#command是一个字典,使用get获取cmd对应的value,value是一个函数对象
d = Dispatcher()
d.run_def("yiyi",lambda self:print("my name is yiyi"))
d.run_def("age",lambda self:print("i am 18 years old"))
d.run_def(100,lambda self:print("i am 18 years old"))
d.dispatcher()
*************run_result************
error
>>yiyi
my name is yiyi
>>age
i am 18 years old
>>prror
Unknown comnmand
>>quit
__getarrt__()
方法触发条件:访问类中的属性的时候,如果属性不存在,就会触发该方法print(实例.属性)
__getarrt__()
方法的return语句中__getarrt__()
方法,如果没有这个方法,就会抛出AttributeEooror的异常,表示找不到该属性getattr()
.
设置属性,如同self.x = x,就会调用__setattr__()
,属性要加到实例的__dict__
中,就需要自己完成__setattr__()
方法,可以拦截对实例属性的增加,修改操作,如果要设置生效,需要自己操作实例的__dict__
对象/实例.属性=新值
__delattr__()
可以阻止通过实例删除属性的操作,但是通过类可以删除属性;通过属性删除,执行__delattr__
魔术方法下的代码del 实例.属性名
__getattribute__()
,他阻止了属性的查找__getarrt__()
方法,表示属性没有找到__getattribute__()
方法中为了避免在该方法中无限的递归,他的实现应该永远调用父类的同名方法以访问需要的任何属性__getattribute__()
方法用来做什么,否则不要用它class Base:
n=0
class Point(Base):
z = 6
def __init__(self,x,y):
self.x = x
self.y = y
def show(self):
print(self.x,self.y)
def __setattr__(self, key, value):
print(key,value)
self.__dict__[key] = value # 自己操作实例的字典赋值
def __getattr__(self, item):
# 按照实例属性,类属性,祖先类的属性和getattr方法找寻函数
# 如果没有找到,执行这个方法下的方法
print("__getattr__:",item)
return "missing :{0}".format(item)
def __delattr__(self, item):
print("__delattr__")
def __getattribute__(self, item):
print("__getattribute__:",item)
# return self.__dict__[item] # 进入递归调用的死死循环,不能这样做
#raise AttributeError("Not Found") # 不行,执行下一步赋值的时候,报错
return object.__getattribute__(self,item)
p = Point(4,5)
print("赋值前实例的字典:",p.__dict__)
p.a = 100
p.y = 200
print("赋值后实例的字典:",p.__dict__)
# 查找顺序:实例的初始化,类的属性,父类的属性
print("子类初始化:",p.x,p.y)
print("子类属性:",p.z)
print("父类属性:",p.n)
print("----------无属性,执行获取的魔术方法---------")
print("无属性:",p.d)
print("---------删除魔术方法生效----------")
del p.x
print("删除实例属性后的字典:",p.__dict__)
************没有__getattribute__之前的run_result**********
x 4
y 5
赋值前实例的字典: {'x': 4, 'y': 5}
a 100
y 200
赋值后实例的字典: {'x': 4, 'y': 200, 'a': 100}
子类初始化: 4 200
子类属性: 6
父类属性: 0
----------无属性,执行获取的魔术方法---------
__getattr__: d
无属性: missing :d
---------删除魔术方法生效----------
__delattr__
删除实例属性后的字典: {'x': 4, 'y': 200, 'a': 100}
************__getattribute__之后的run_result**********
x 4
__getattribute__: __dict__
y 5
__getattribute__: __dict__
__getattribute__: __dict__
赋值前实例的字典: {'x': 4, 'y': 5}
a 100
__getattribute__: __dict__
y 200
__getattribute__: __dict__
__getattribute__: __dict__
赋值后实例的字典: {'x': 4, 'y': 200, 'a': 100}
__getattribute__: x
__getattribute__: y
子类初始化: 4 200
__getattribute__: z
子类属性: 6
__getattribute__: n
父类属性: 0
----------无属性,执行获取的魔术方法---------
__getattribute__: d
__getattr__: d
无属性: missing :d
---------删除魔术方法生效----------
__delattr__
__getattribute__: __dict__
删除实例属性后的字典: {'x': 4, 'y': 200, 'a': 100}
__get__()
、__set__()
、__delete__()
__get__(self, instance, owner)
、__set__(self, instance, value)
、__delete__(self, instance)
__get__()
,就是非数据描述器__get__()
、__set__()
或者__delete__()
中的一个,就是数据描述器class A :
def __init__(self):
print("A init")
self.a = "a1"
def __get__(self, instance, owner):
print("A实例:{},instance参数:{},谁调用:{}".format(self,instance,owner))
class B :
x = A() # x存储的是一个描述器对象
# 描述器会肤隔离类属性的相关操作
# 直接触发的是描述器中的get、set和delete方法
def __init__(self):
print("B init")
self.x = 100
print("B类中x的属性,就是A():",B.x)
# 在没有__get__方法的情况下,下面这句代码可执行,返回结果为A初始化函数中a的值
# print("B类中x的属性,就是A():",B.x.a)
# 存在描述起,B.x的返回值就是None,没有a属性
# B类没有实例化,所以在此B中初始化函数没有执行,
# 因此没有打印B初始化函数中的字符串
# 这里的结果是None,因为初始化函数的返回值就是None
b = B()
print("B实例中x的属性,为init中的数据",b.x)
**********run——result*************
A init
A实例:<__main__.A object at 0x1044fba30>,instance参数:None,
谁调用:<class '__main__.B'>
B类中x的属性,就是A(): None
B init
B实例中x的属性,为init中的数据 100
__get__
方法__get__
魔术方法的情况下,b.x会查找类下的x属性,指向A的实例,可调用b.x.a
__get__
的魔术方法,类A就是一个描述起,对类B或者类B的实例的x属性读取,成为了A的实例的访问,就会调用__get__
方法class A :
def __init__(self):
print("A init")
self.a = "a1"
def __get__(self, instance, owner):
print("A实例:{},instance参数:{},谁调用:{}".format(self,instance,owner))
class B :
x = A()
def __init__(self):
print("B init")
# B实例的初始化中没有x,就调用类属性的x
# 也就是A(),这样A又重新执行初始化函数
print("B类中x的属性,就是A():",B.x)
b = B()
print("B实例中x的属性,为init中的数据",b.x)
*************run_result***********
A init
A实例:<__main__.A object at 0x10510b9a0>,
instance参数:None,谁调用:<class '__main__.B'>
B类中x的属性,就是A(): None
B init
A实例:<__main__.A object at 0x10510b9a0>,
instance参数:<__main__.B object at 0x10510b8e0>,谁调用:<class '__main__.B'>
B实例中x的属性,为init中的数据 None
__get__
方法__get__
方法后,其没有返回值,因此返回值为None,因此B类的属性A()的返回值就是None,故无法调用A类中的a属性__get__
,打印相关信息,class A :
def __init__(self):
print("A init")
self.a = "a1"
def __get__(self, instance, owner):
return self
class B :
x = A()
def __init__(self):
print("B init")
print("B类中x的a属性,就是A():",B.x.a)
b = B()
print("B实例中x的属性,为init中的数据",b.x)
***********run_rerult*******
A init
B类中x的a属性,就是A(): a1
B init
B实例中x的属性,为init中的数据 <__main__.A object at 0x10474f970>
__get__
class A :
def __init__(self):
print("A init")
self.a = "a1"
def __get__(self, instance, owner):
print("A实例:{},instance参数:{},谁调用:{}".format(self,instance,owner))
return self
class B :
x = A()
def __init__(self):
print("B init")
self.x = A() # 实例属性指向A的实例
print("B类中x的a属性,就是A():",B.x.a)
b = B()
print("B实例中x的属性,为init中的数据",b.x)
************run_result*************
A init
B类中x的a属性,就是A(): a1
B init
A init ——>B类中调用A的实例,A执行初始化函数,但是没有执行描述器方法
B实例中x的属性,为init中的数据 <__main__.A object at 0x104537910>
__set__
和 __delete__
class A :
def __init__(self):
print("A init")
self.a = "a1"
def __get__(self, instance, owner):
print("A实例:{},instance参数:{},谁调用:{}".format(self,instance,owner))
return self
def __set__(self, instance, value):
print("__set__的self:{},instance:{}" .format(self,instance))
print("__set__的value信息,接收B实例中同名函数的值:",value)
class B :
x = A()
def __init__(self):
print("B init")
self.x = 100 # 实例属性指向A的实例
b = B()#B实例化后,首先自动执行类属性x,即B.x ;
#B实例化,自动执行B的初始化函数;然后自动执行set函数
print("B实例中x的属性,为init中的数据",b.x)
# 实例中的x和属性同名,调用的是属性中的x,因此返回A的实例
*************************run_result*************************
A init
B init
__set__的self:<__main__.A object at 0x0000026CC7614FD0>,
instance:<__main__.B object at 0x0000026CC7614E80>
__set__的value信息,接收B实例中同名函数的值: 100
A实例:<__main__.A object at 0x0000026CC7614FD0>,instance参
数:<__main__.B object at 0x0000026CC7614E80>,谁调用:<class
'__main__.B'>
B实例中x的属性,为init中的数据
<__main__.A object at 0x0000026CC7614FD0>
class Bases:
def __init__(self,a,b):
self.a = a
self.b = b
def count(self):
print("Bases:这是一个加法运算")
return "a+b={0}".format(self.a+self.b)
class SonOne(Bases):
def __init__(sel,a,b):
super().__init__(a,b)
def count(self):
print("SonOne:这是一个减法运算")
return"a-b={0}".format(self.a - self.b)
class SonTwo(Bases):
def __init__(self, a, b):
super().__init__(a, b)
def count(self):
print("SonTwo:这是一个乘法运算")
return "a*b={0}".format(self.a*self.b)
class SonThree(Bases):
pass
b_obj = Bases(4,5)
s1_ogj = SonOne(4,5)
s2_ogj = SonTwo(4,5)
s3_ogj = SonThree(4,5)
# 传入的参数必须是类的对象
def func(base_obj):
res = base_obj.count()
return res
print(func(b_obj))
print(func(s1_ogj))
print(func(s2_ogj))
print(func(s3_ogj))
*******************run_result*********************
Bases:这是一个加法运算
a+b=9
SonOne:这是一个减法运算
a-b=-1
SonTwo:这是一个乘法运算
a*b=20
Bases:这是一个加法运算
a+b=9