昨日内容练习
class A:
def func1(self):pass # func1 普通方法
@classmethod
def func2(self):pass # func2 类方法
@staticmethod
def func3(self):pass # func3 静态方法
# func1 普通方法 对象和类绑定的过程
a = A()
b = A()
print(A.func1) # 3个地址都不一样
print(a.func1)
print(b.func1)
# func2 类方法 由于不适用对象内存空间中的属性,
# 所以不会将对象和方法绑在一起,而是将类和方法绑在一起
print(A.func2)
print(a.func2) # 对象能找到类,类里面绑着方法
print(b.func2)
# func3 静态方法 不是绑定方法 没有和对象或者类发生任何绑定关系
print(A.func3)
print(a.func3)
print(b.func3)
执行结果
1 普通方法,func1结果
<bound method A.func1 of
<bound method A.func1 of
2 类方法,func2结果
<bound method A.func2 of
<bound method A.func2 of
<bound method A.func2 of
3 静态方法,func3结果
isinstance(对象名,类名) 返回True,False
isinstance(obj,cls)检查obj是否是类cls的对象
例子
class A:pass
class B(A):pass
b = B()
print(isinstance(b, A)) # 能够检测到继承关系
print(isinstance(b, B))
print(type(b) is A)
print(type(b) is B) # type只单纯的判断类
执行结果
True
True
False
True
issubclass(子类名,父类名) 返回True,False
issubclass(sub,super)检查sub类是否是super类的派生类
例子,单继承
class A:pass
class B:pass
class C(B):pass
class D(C):pass
print(issubclass(C,B)) # 判断C是不是B的子类
print(issubclass(D,C)) # 判断D是不是C的子类
print(issubclass(D,B)) # 判断D是不是C的子类
print(issubclass(D,A)) # 判断D是不是A的子类
执行结果
True
True
True
False
例子2,多继承
class A:pass
class B:pass
class C(A,B):pass
class D(C):pass
print(issubclass(C,A)) # 判断C是不是A的子类
print(issubclass(C,B)) # 判断C是不是B的子类
print(issubclass(D,B)) # 判断D是不是B的子类
print(issubclass(D,A)) # 判断D是不是A的子类
执行结果
True
True
True
True
面向对象进阶(反射,非常重要的知识点*******7星)
1 什么是反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问,检测和修改它本身状态或行为的一种能力(自省),它首先被程序语言的设计领域所采用,并在Lisp和面向对象取得了成绩
2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
四个可以实现自省的函数
下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
反射
正常情况下如果可以拿到这个变量, 那么如有这个变量的字符串形式,就是用反射可以获取到这个值
使用字符串数据类型的变量名 访问一个命名空间中的名字
找一个属性,直接就可以找到这个属性的值
找一个方法,找到的是这个方法的内存地址
getattr 使用字符串数据类型的变量名 访问一个命名空间中的名字
源代码
def getattr(object, name, default=None): # known special case of getattr
"""
getattr(object, name[, default]) -> value
Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
"""
pass
例子
class A:
role = 'person' # 静态属性
def func(self):
print('*'*10)
print(A.__dict__['role']) # 查看静态属性的值
ret = input('>>>') # 用户输入role
print(A.__dict__[ret]) # 实际上就是执行了最上面的print
执行结果
person
>>>role
person
那么如何让用户输入func然后去执行类里面的方法func呢?
class A:
role = 'person' # 静态属性
def func(self):
print('*'*10)
ret = input('>>>') # 用户输入func
# 这里要用到字符串拼接+eval函数才能实现
s = 'A'
ss = s + '.' + ret
eval(ss)(1)
执行结果
>>>func
**********
这样很麻烦,也不安全,还有什么方法呢?
getattr() 从命名空间中获取这个名字对应的值
class A:
role = 'person' # 静态属性
def func(self):
print('*'*10)
# 从A的命名空间里找一个属性,直接就可以找到这个属性的值
# 通俗点就是需要获取谁(func),就是getattr(A,'func') getattr(类,'属性名')
print(getattr(A, 'role'))
a = A() # 实例化一个对象a
# 从A的命名空间里面找一个方法,找到的是这个方法的内存地址,如果要执行这个方法,在后面加()
print(getattr(a, 'func'))
getattr(a, 'func')()
#getattr如何让用户输入一个类中的方法名,并执行
ret = input('>>>:')
getattr(a, ret)() # getattr(a, ret)实际上获取的就是func方法的内存地址,后面加()就表示执行
执行结果
person
<bound method A.func of
**********
>>>:func
**********
例2
class A:
role = 'Person'
def __init__(self):
self.money = 500
def func(self):
print('*'*10)
a = A()
print(a.func) # 打印a.func的内存地址
getattr(a, 'func')() # 使用getattr获取名字对应的值,名字加()就表示执行这个方法
print(getattr(a, 'money')) # 使用getattr获取名字对应的值
执行结果
<bound method A.func of
**********
500
hasattr() 判断一个命名空间中有没有这个名字
源码
def hasattr(*args, **kwargs): # real signature unknown
"""
Return whether the object has an attribute with the given name.
This is done by calling getattr(obj, name) and catching AttributeError.
"""
pass
例1
class A:
role = 'person'
def func(self):
print('py3study.com')
a = A()
print(hasattr(a, 'r')) # 也可以写成 print(hasattr(A, 'r'))
print(hasattr(a, 'role'))
print(hasattr(a, 'func'))
执行结果
False
True
True
hasattr()经常与getattr()一起用,首先判断一个命名空间中有没有这个名字,有的话就用getattr获取这个名字对应的值
示例
class A:
role = 'person'
def func(self):
print('py3study.com')
ret = input('>>>')
if hasattr(A, ret): # 判断是否存在
print(getattr(A, ret)) # 如果存在则打印内存地址
if hasattr(A, ret):
func = getattr(A, ret) # 如果存在则执行这个方法
func(1)
else:
print('error') # 不存在则报错
执行结果
>>>func
py3study.com
类使用类命名空间中的名字
对象使用对象能用的方法和属性
模块使用模块中的名字
导入os模块,利用getattr获取os模块中'rename'对应的值,os.rename('old','new')执行改文件名的操作
import os;getattr(os, 'rename')('user', 'user_info')
导入time模块,利用getattr获取time模块中'time'对应的值,print(time.time())打印时间戳
import time;print(getattr(time, 'time')())
从自己所在的模块中使用自己名字
示例
def login():
print('执行login功能')
def register():
print('执行register功能')
import sys
print(sys.modules['__main__']) # 打印当前文件的路径,一个.py文件就相当于一个模块
func = input('>>>')
if hasattr(sys.modules['__main__'], func): # 判断当前模块中的命名空间,是否有用户输入的这个名字
getattr(sys.modules['__main__'], func)() # 存在的话执行用户输入的名字加()这个函数
执行结果
>>>login
执行login功能
类使用类命名空间中的名字
getattr(类名,'名字')
对象使用对象能用的方法和属性
getattr(对象名,'名字')
模块使用模块中的名字
导入模块
getattr(模块名,'名字')
从自己所在的模块中使用自己名字
import sys
getattr(sys.modules['__main__'],名字)
getattr一定要和hasattr配合使用
反射 :4个内置函数
getattr # 从命名空间中获取这个名字对应的值
hasattr # 判断一个命名空间中有没有这个名字
setattr # 修改和新建
delattr # 删除一个属性
setattr,delattr
setattr源码
def setattr(x, y, v): # real signature unknown; restored from __doc__
"""
Sets the named attribute on the given object to the specified value.
setattr(x, 'y', v) is equivalent to ``x.y = v''
"""
pass
delattr源码
def delattr(x, y): # real signature unknown; restored from __doc__
"""
Deletes the named attribute from the given object.
delattr(x, 'y') is equivalent to ``del x.y''
"""
pass
增删改 对象属性
class A:
def __init__(self, name):
self.name = name
def wahaha(self):
print('噢噢噢噢哦哦哦')
a = A('Sam')
print(a.name)
a.wahaha()
print(a.__dict__)
# 使用setattr: 无则增加有则修改的原则
setattr(a, 'age', 18) # 给a对象新增一个属性
print(a.__dict__)
a.wahaha() # 执行wahaha()方法
# 使用setattr: 无则增加有则修改的原则
setattr(a, 'name', 'Jack') # 修改a对象的name属性为Jack
print(a.__dict__)
del a.name # 删除a对象的name属性
print(a.__dict__)
# 使用delattr删除
delattr(a, 'age')
print(a.__dict__)
执行结果
Sam
噢噢噢噢哦哦哦
{'name': 'Sam'}
{'name': 'Sam', 'age': 18}
噢噢噢噢哦哦哦
{'name': 'Jack', 'age': 18}
{'age': 18}
{}
例2
class A:
def __init__(self, name):
self.name = name
def wahaha(self):
print('aaaaaaaaaaa')
def qqxing(self):
print('qqqqqqqqq')
a = A('Tom')
setattr(a, 'qqxing', qqxing) # setattr把函数qqxing 加到类里面去了
a.qqxing(a)
# 使用getattr函数从命名空间中获取这个名字对应的值
getattr(a, 'qqxing')(a)
执行结果
qqqqqqqqq
qqqqqqqqq