反射:用带字符串类型的名字 去获取 变量
一、类中的反射
在学反射以前,我们也学习了一种方法,可以获取字符串中的变量 eval()但是安全性不高
name = "duke"
eval("print(name)") #duke
因为前面介绍的是类,因此我们便已类来介绍反射的使用方法;反射 有四个函数 getatter()获取变量;hasatter()查询字符串中变量是否存在;seratter(),更改字符串中变量的值;delatter 删除字符串中的属性值。前两者使用相当广泛,且经常搭配使用;而后两者的使用场景较少,且有一定的安全隐患。
使用方法 :getatter(对象\类,"string") 反射对象的方法,如果实在类的普通方法的内部是用,self即为函数对象
class A:
def func(self):
print("in func")
a = A()
a.name = "alex" #给a对象添加一个数据属性name
#反射对象的属性 getatter(对象,属性名的字符串形式)
ret = getattr(a,"name") #通过变量名的字符串的形式取到的值
print(ret)
print(a.__dict__) #{'name': 'alex'}该方法只存数据属性,不存方法
# 变量名 =input(">>>>:").strip()
# print(getattr(a,变量名))
#反射对象的方法 getatter(对象,属性方法的字符串形式) 拿到一个绑定方法 +()执行
ret = getattr(a,"func") #返回该方法的内存地址
ret()#加括号便能执行,若该方法需要传参,直接在()内按照函数传参的方式传入即可
反射类:在class 中 还有两种方法 @staticmethod静态方法 @classmethod类方法 同样也有类变量
反射类的属性
class A:
price = 20
@classmethod
def func(cls,name):
print("%s in func" % name)
@staticmethod
def dunc1():
print("静态方法")
#反射类的数据获取
print(getattr(A,"price")) #20
#反射类的方法 classmethod staticmethod(这两种方法完全可以由类名调用)
getattr(A,"func")("duke") #duke in func
getattr(A,"dunc1")() #静态方法
我们在学习的过程不仅类与对象可以采用x.x 的当时执行;模块也可以使用这种方法;,同样模块也可以使用反射
模块反射:也有数据和方法两种,使用方法同上
使用模块如下:模块名 my_moudle.py
day = "Monday"
def refraction_test():
print("test successful")
class C:
c= 255
def fun(self):
print("模块中的普通方法类")
@classmethod
def fun2(cls):
print("模块中的类方法")
测试如下:
#模块里面的反射
import my_moudle
# print(my_moudle.day)
print(getattr(my_moudle,"day"))#静态方法
#反射模块的方法 同对象与类
getattr(my_moudle,"refraction_test")()#test successful
#反射模块的类
#获得对象如果加括号 则等于创建了一个对象
refraction_object = getattr(my_moudle,"C")()
refraction_object.fun() #模块中的普通方法类
print(getattr(refraction_object,"c")) #255
#未加括号 则相当于 把那个类给借调过来了
refraction_class = getattr(my_moudle,"C")
print(refraction_class.c) #255
getattr(refraction_class,"fun2")() #模块中的类方法
一个py文件就是一个模块,能够在导入的模块中使用反射,那能不能在当前文件中使用反射,当然是可以,首先我们需要或得到当前文件对应的模块名。
import sys
for i in sys.modules:
print("%-20s%s" %(i,sys.modules[i]))
"""
sys <module 'sys' (built-in)>
builtins <module 'builtins' (built-in)>
_frozen_importlib <module '_frozen_importlib' (frozen)>
_imp <module '_imp' (built-in)>
_thread <module '_thread' (built-in)>
_warnings <module '_warnings' (built-in)>
_weakref <module '_weakref' (built-in)>
zipimport <module 'zipimport' (built-in)>
_frozen_importlib_external <module '_frozen_importlib_external' (frozen)>
_io <module 'io' (built-in)>
marshal <module 'marshal' (built-in)>
nt <module 'nt' (built-in)>
winreg <module 'winreg' (built-in)>
encodings <module 'encodings' from 'F:\\python\\lib\\encodings\\__init__.py'>
codecs <module 'codecs' from 'F:\\python\\lib\\codecs.py'>
_codecs <module '_codecs' (built-in)>
encodings.aliases <module 'encodings.aliases' from 'F:\\python\\lib\\encodings\\aliases.py'>
encodings.utf_8 <module 'encodings.utf_8' from 'F:\\python\\lib\\encodings\\utf_8.py'>
_signal <module '_signal' (built-in)>
__main__ <module '__main__' from 'F:/code/文件夹 类的反射/反射.py'>
encodings.latin_1 <module 'encodings.latin_1' from 'F:\\python\\lib\\encodings\\latin_1.py'>
io <module 'io' from 'F:\\python\\lib\\io.py'>
abc <module 'abc' from 'F:\\python\\lib\\abc.py'>
_abc <module '_abc' (built-in)>
site <module 'site' from 'F:\\python\\lib\\site.py'>
os <module 'os' from 'F:\\python\\lib\\os.py'>
stat <module 'stat' from 'F:\\python\\lib\\stat.py'>
_stat <module '_stat' (built-in)>
ntpath <module 'ntpath' from 'F:\\python\\lib\\ntpath.py'>
genericpath <module 'genericpath' from 'F:\\python\\lib\\genericpath.py'>
os.path <module 'ntpath' from 'F:\\python\\lib\\ntpath.py'>
_collections_abc <module '_collections_abc' from 'F:\\python\\lib\\_collections_abc.py'>
_sitebuiltins <module '_sitebuiltins' from 'F:\\python\\lib\\_sitebuiltins.py'>
sitecustomize <module 'sitecustomize' from 'F:\\pycharm\\PyCharm 2018.2.5\\helpers\\pycharm_matplotlib_backend\\sitecustomize.py'>
my_moudle <module 'my_moudle' from 'F:\\code\\文件夹 类的反射\\my_moudle.py'>
time <module 'time' (built-in)>
"""
从sys.moudles 中我们可以得知__main__ 对应的模块名为:"__main__"
import sys
year = 2018
def test():
print("test")
import sys
print(sys.modules["__main__"]) #表示自己模块 <module '__main__' from 'F:/code/文件夹 类的反射/反射.py'>
print(getattr(sys.modules["__main__"],"year")) #2018
getattr(sys.modules["__main__"],"test")() #test
当然,我们也知道,当被导入使用时,__main__ 就不会表示原先的py文件,表示便会时当时的执行文件,这是就需要用到__name__这个方法了,当在本文件运行=__main__,不再本文件运行时,则不等于__main__=模块名,因此上面那个式子,应该改进一下:
print(getattr(sys.modules[__name__],"year")) #2018
同样,若反射能在自定义模块中执行,自然能在内置模块中使用,以time模块为例
import time
print(getattr(time,"time")()) #1542720516.2940655