发布时间:2018-04-18 20:10:56编辑:Run阅读(3676)
昨日内容练习
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
47745
46235
37110
34627
29229
25886
24745
19863
19417
17908
5716°
6315°
5835°
5888°
6984°
5829°
5846°
6361°
6316°
7673°