多态:一个类型表现出来多种状态。python中一个子类可以表现其本身的类型,同时它还具有其所有父类的类型。
先看一个实例:
class A:
def func(self):print(‘A‘)
class B(A):
def func(self):
super().func()
print(‘B‘)
class C(B):
def func(self):
super().func()
print(‘C‘)
C().func()
"""
A
B
C
"""
# 可以看出super好像是寻找父类
# 其实只是在单继承的情形下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‘)
D().func()
"""
A
C
B
D
"""
# 但其实super是按照MRO顺序来寻找当前类的上一个类
# 而MRO顺序是根据C3算法计算得出的
广义上:把方法和属性封装起来,外部不能直接调用,只能通过类的名字调用。
狭义上:把方法和属性封装起来,外部不能调用,只能类内部使用。
class A(object):
def __init__(self,username,passwd):
self.username = username
self.__pswd = passwd
def get_pswd(self):
return self.pswd
def change_pswd(self):
pass
# 在给对象的一个属性前加上了双下划线__后,称这个属性为私有的
# 所有私有的方法或者属性都不能在类的外部调用,只能在类的内部使用
# 但是可以在类的内部定义方法使得在外部能够查看私有属性(如get_私有属性名)
# 但是这个方法只能查看,不能修改!
# 当然如果想修改的话也可以定义一个修改函数,只能根据修改函数指定的方式改(change_私有属性名)
# 私有的静态变量如下:
class A:
count = 1 # 非私有
__num = 2 # 私有
# 可以在内部定义方法查看私有静态变量
def func(self):
print(A.__num)
print(A.count) # 1
A().func() # 2
print(A.__num) # AttributeError: type object ‘A‘ has no attribute ‘__num‘
所有的私有化都是为了让用户不在外部调用类内部的某个名字(静态变量,方法,属性等)。
完成了私有化的类的封装度更高,相应的其各种属性和方法的安全度也更高,但是代码相对也变得更加复杂。
那么加了双下划线的名字为什么不能从类的外部调用了呢?
# 观察一个有私有静态变量的类
class A:
num1 = 1
__num2 = 2
__num3 = 3
# 查看类的内容
print(A.__dict__)
# {‘__module__‘: ‘__main__‘, ‘num1‘: 1, ‘_A__num2‘: 2, ‘_A__num3‘: 3, ‘__dict__‘: <attribute ‘__dict__‘ of ‘A‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘A‘ objects>, ‘__doc__‘: None}
# 可以看到私有静态变量变成了_A__num2和_A__num3
# 试着用这种名字进行调用
print(A()._A__num2) # 2
print(A()._A__num3) # 3
# 所以私有化并不是真正的无法调用,只是对象名字被另一种规则更改了
私有的内容能否被子类使用?
class A:
def __init__(self):
self.__func()
def __func(self): # 这个函数实际是_A__func
print(‘A‘)
class B(A):
def __func(self): # 这个函数实际是_B__func
print(‘B‘)
B() # A
# !!!上述代码实现过程:
# 在调用B()的时候,创建B类的实例,首先寻找__init__方法
# 由于B类自己没有这个方法,所以去父类(A类)寻找
# 在A的__init__方法中执行self.__func()
# 实际上是执行self._A__func(),而这个方法在B类中没有
# 所以去A类中寻找,执行的是print(‘A‘)!
所以,私有的内容不能被子类使用!!!
在其他语言中数据的级别都有哪些,在python中又有哪些
python支持public和private,不支持protect。
在类内部的方法定义前加上@property,将方法伪装成属性。(property装饰的方法不能有其他参数)
from math import pi
class circle:
def __init__(self,r):
self.r = r
@property
def area(self):
return pi*self.r**2
a = circle(3)
print(a.r) # 3
print(a.area) # 28.274333882308138
# 这里将area方法伪装成了一个属性
# 调用的时候不需要使用实例化对象.area()
property装饰器的加入是为了使逻辑完善。就像上述代码中的例子,对于circle类来说,它的半径r是一个属性,而它的面积按照逻辑来说也应该是一个circle的属性而不应该是它的一个方法(一般而言,名词一般是一个属性,动词更像是一个方法)。所以说property一般可以去修饰一些容易变动(变动的值需要通过方法实现)的属性。
# property的其他使用
class User:
# 定义用户名和密码
def __init__(self,usr,pwd):
self.usr = usr
self.__pwd = pwd
# 查看密码
@property
def pwd(self):
return self.__pwd
# 修改密码
@pwd.setter
def pwd(self,new_pwd):
# 在这里修改可以设置要求
if isinstance(new_pwd,str):
self.__pwd = new_pwd
user = User(‘aaa‘,‘123‘)
print(user.pwd) # 123
user.pwd = ‘456‘
print(user.pwd) # 456
# 尝试设置数字为密码
user.pwd = 789
print(user.pwd) # 456
# 密码修改失败
# property除了setter方法外还有一个deleter方法(不常用)可以删除属性
# 用法跟setter基本一样
用字符串数据类型的名字来操作这个名字对应的函数\实例变量\绑定方法。
反射对象的实例变量,反射类的静态变量、绑定方法
class Person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def func(self):
print(‘function‘)
Lieve = Person(‘Lieve‘,22)
Mark = Person(‘Mark‘,23)
# 调用属性
ret1 = getattr(Lieve,‘name‘) # 反射对象的实例变量
ret2 = getattr(Lieve,‘age‘)
print(ret1,‘,‘,ret2) # Lieve , 22
ret3 = getattr(Mark,‘name‘)
ret4 = getattr(Mark,‘age‘)
print(ret3,‘,‘,ret4) # Mark , 23
# 调用方法
f1 = getattr(Lieve,‘func‘) # 反射对象的绑定方法
f1() # function
# 将调用方式对象名.属性(方法)名==>getattr(对象名,‘属性(方法)名‘)
# 反射类的静态变量、绑定方法可同样实现
# 类名.属性(方法)名==>getattr(类名,‘属性(方法)名‘)
反射模块(包括被导入的模块,当前执行的py文件即脚本)中的所有变量
模块名.属性(方法)名==>getattr(模块名,‘属性(方法)名‘)
原文:https://www.cnblogs.com/20-03-14/p/12622388.html