一、super 方法
class A:
def func(self):
print('A')
class B(A):
def func(self):
super().func()
print('B')
class C(A):
def func(self):
super().func()
print('C')
class D(B,C):
def func(self):
super().func()
print('D')
print(D.mro())
# [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
D().func()
'''
A
C
B
D
'''
- super 是按照mro顺序来寻找当前类的下一个类的
- 在python3中不需要传参数,自动就帮我们寻找当前类的mro顺序的下一个类中的同名方法
- 在python2中的新式类中,需要我们主动传递参数super(子类的名字, 子类的对象).函数名(),这样才能够帮我们调用到这个子类的mro顺序的下一个类中的方法。
- 在python2的经典类中,并不支持使用super来找下一个类。
即上面代码在D类中找super的func,可以写super().func()
,也可写成super(D, self).func()
,但是在python2中必须写成super(D, self).func()
在单继承的程序中,super就是找父类。
class User:
def __init__(self, name):
self.name = name
class VIPUser(User):
def __init__(self, name, level, start_time, end_time):
super().__init__(name)
self.level = level
self.start_time = start_time
self.end_time = end_time
jason = VIPUser('jason', 10, '05-03', '06-03')
print(jason.__dict__)
# {'name': 'jason', 'level': 10, 'start_time': '05-03', 'end_time': '06-03'}
二、封装
封装:把属性和方法装起来
广义:把属性和方法装起来,外部不能直接调用,要通过类的名字调用
狭义:把属性和方法藏起来,外部不能调用,只能在内部偷偷调用
- 给一个名字前面加上双下划线的时候,这个名字就变成了一个私有的
所有的私有的内容或名字都不能在类的外部直接调用,只能在类的内部使用
class User:
def __init__(self, username, password):
self.usr = username
self.__pwd = password # 私有的实例变量/私有的对象属性
jason = User('jason', '123456')
print(jason.usr) # jason
print(jason.__pwd) # 此时会报错
- 如果想要查看或者修改私有的实例变量只能在类中定义函数来查看
class User:
def __init__(self, username, password):
self.usr = username
self.__pwd = password # 私有的实例变量/私有的对象属性
def get_pwd(self):
return self.__pwd
def change_pwd(self):
old_pwd = input('enter old password:')
if old_pwd == self.__pwd:
new_pwd1 = input('enter new password:')
new_pwd2 = input('enter new password again:')
if new_pwd1 == new_pwd2:
self.__pwd = new_pwd2
jason = User('jason', '123456')
print(jason.usr) # jason
print(jason.get_pwd()) # 123456
jason.change_pwd()
print(jason.get_pwd())
同理,也可以有私有的静态变量
class Map:
country = 'china'
__language = 'chinese'
def get(self):
return Map.__language
a = Map()
print(a.country) # china
print(a.__language) # 报错
print(a.get()) # chinese
同理,也可以有私有的方法
import hashlib
class User:
def __init__(self,name,password):
self.usr = name
self.__pwd = password # 私有的实例变量
def __md5_pwd(self): # 私有的方法
ret = hashlib.md5()
ret.update(self.__pwd.encode('utf-8'))
return ret.hexdigest()
def get_pwd(self):
return self.__md5_pwd()
jason = User('jason', 'abcd')
print(jason.get_pwd())
所有的私有化都是为了让用户不在外部调用类中的某个名字
如果完成私有化,那么这个类的封装度就更高了,封装度越高各种属性和方法的安全性也越高 ,但是代码越复杂
私有的内容能不能被子类使用? 不能
class Foo:
def __init__(self):
self.func()
def func(self):
print("in Foo")
class Son(Foo):
def func(self):
print("in Son")
Son() # in Son
class Foo:
def __init__(self):
self.__func()
def __func(self):
print("in Foo")
class Son(Foo):
def __func(self):
print("in Son")
Son() # in Foo
class Foo:
def __func(self):
print("in Foo")
class Son(Foo):
def __init__(self):
self.__func()
Son() # 报错
三、类中的装饰器
- property
property 应用场景一:把一个方法伪装成属性,在调用这个方法时不需要加()就可以直接得到返回值
import time
class Person:
def __init__(self, name, birth):
self.name = name
self.birth = birth
@property
def age(self): # 装饰的这个方法,不能有参数
return time.localtime().tm_year - self.birth
jason = Person('jason', 1996)
print(jason.age)
property 应用场景二:和私有属性合作
class User:
def __init__(self,username,password):
self.usr = username
self.__pwd = password
@property
def pwd(self):
return self.__pwd
jason = User('jason', 1234)
print(jason.pwd)
property 进阶
class Goods:
discount = 0.8
def __init__(self,name,origin_price):
self.name = name
self.__price = origin_price
@property
def price(self):
return self.__price * self.discount
@price.setter
def price(self,new_value):
if isinstance(new_value,int):
self.__price = new_value
apple = Goods('apple', 10)
print(apple.price) # 调用的是被@property装饰的price
apple.price = 20 # 调用的是被setter装饰的price
print(apple.price)
三、反射
反射使用场景
1.反射对象的实例变量
2.反射类的静态变量/绑定方法/其他方法
3.模块中的所有变量:导入的模块/当前.py文件
语法
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def func(self):
print('aloha')
j = Person('jason', 24)
d = Person('dog', 5)
ret = getattr(j, 'name')
print(ret)
ret = getattr(d, 'func')
ret()
使用反射实现归一化
import sys
class Wechat:
def __init__(self, name):
self.name = name
def pay(self, money):
print(f'{self.name}通过微信支付了{money}元。')
class Alipay:
def __init__(self, name):
self.name = name
def pay(self, money):
print(f'{self.name}通过支付宝支付了{money}元。')
def pay(name, price, type):
class_name = getattr(sys.modules['__main__'], type)
obj = class_name(name)
obj.pay(price)
pay('jason', 400, 'Wechat')
反射的另一个函数 hasattr
class A:
def __init__(self):
self.name = 'jason'
self.age = 24
def func(self):
return 666
j = A()
if hasattr(j,'name'):
print(getattr(j,'name'))
if hasattr(j,'age'):
print(getattr(j,'age'))
if hasattr(j,'sex'):
print(getattr(j,'sex'))