python学习day27 反射 内置的类方法1

isinstance(obj,cls) 检查obj是否是cls类的对象

issubclass(sub,super) 检查sub类是否是super类的子类

反射

是用字符串类型的名字 去操作 变量

为什么不用eval()?

name = 1
eval('print(name)')   # 1

因为eval()操作的是一个字符串代码,这段字符串我们拿过来对立面的信息什么都不知道,会有很大的安全隐患

而反射只是通过字符串来操作内存里的变量

  • setattr
  • delattr
  • getattr
  • hasattr

反射对象的属性和方法

class A:
    def func(self):
        print('in func')

a = A()
a.name = 'alex'
a.age = 63

# 反射对象的属性
ret = getattr(a, 'name')  # 通过变量名的字符串形式取到的值
print(ret)  # 'alex'
print(a.__dict__)  # 查看对象a中的所有属性
变量名 = input('>>>')   # func
print(getattr(a, 变量名))
print(a.__dict__[变量名])  #也可以通过这样来调用属性

# 反射对象的方法
a.func()
ret = getattr(a,'func')
ret()  # 执行方法

 

反射的属性和方法

class A:
    price = 20  # 静态属性
    @classmethod
    def func(cls):
        print('in func')


# 反射类的属性 print(getattr(A,'price')) # 反射类的方法 :classmethod staticmethod if hasattr(A,'func'): getattr(A,'func')()

反射模块的属性和方法

定义模块my.py

day = 'Monday'

def wahaha():
    print('wahaha')

反射

import my
# 反射模块的属性
print(my.day)
print(getattr(my,'day'))

# 反射模块的方法
getattr(my,'wahaha')()

反射当前模块的属性和方法

def qqxing():
    print('qqxing')
year = 2018
import sys
# print(sys.modules['__main__'].year)  # sys.modules查看当前模块的名字

# 反射自己模块中的变量
print(getattr(sys.modules['__main__'],'year'))

# 反射自己模块中的函数
getattr(sys.modules['__main__'],'qqxing')()
变量名 = input('>>>')
print(getattr(sys.modules[__name__],变量名))  # 一般情况下用__name__变量 获取当前模块的名字

 

要反射的函数中有参数怎么办?

import time

print(time.strftime('%Y-%m-%d %H:%M:S'))  # 为时间打上格式
print(getattr(time,'strftime')('%Y-%m-%d %H:%M:S'))  # 后面传参就行了

 

setattr和delattr   (不重要)

# setattr  设置修改变量
class A:
    pass
a = A()
setattr(a,'name','nezha')
setattr(A,'name','alex')
print(A.name)
print(a.name)

# delattr 删除一个变量
delattr(a, 'name')
print(a.name)  # alex
delattr(A,'name')
print(a.name)  # 报错

 

 类中的几个内置方法

 

内置的类方法 和 内置的函数之间有着千丝万缕的联系

__repr__  让字符和数字原形毕露

__str__  直接打印对象,走的是__str__下的内容

obj.__str__相当于 str(obj)
obj.__repr__ 相当于 repr(obj)

以上两个内置方法返回的必须是字符串,否则报错

class Teacher:
    def __init__(self,name,salary):
        self.name = name
        self.salary = salary
    def __str__(self):
        return "Teacher's object :%s"%self.name
    def __repr__(self):
        return str(self.__dict__)
    def func(self):
        return 'wahaha'
nezha = Teacher('哪吒',250)
print(nezha)  # 打印一个对象的时候,就是调用a.__str__,如果没有,调用的是a.__repr__
print(str(nezha))
print('>>> %s' %nezha)
print(repr(nezha))  # print(str(nezha))和此功能一样。repr 是str的备胎,但str不能做repr的备胎
print('>>> %r' %nezha)

%s str() 直接打印 实际上都是走的__str__
%r repr() 实际上都是走的__repr__

 如果类中没有__str__却有__repr__方法,%s str()打印出的是__repr__方法,如果__str__和__repr__都没有,打印出来的是Teacher类的内存地址

print(obj), '%s'%obj, str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串

如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。
repr(),只会找__repr__,如果没有找父类的

一般会优先实现__repr__方法

 

__del__ 

析构函数: 在删除一个对象之前进行一些收尾工作

class A:
    def __del__(self):   
        self.f.close()
a = A()
a.f = open()   # 打开文件操作 第一 在操作系统中打开了一个文件 拿到了文件操作符存在了内存中
# del 既执行了这个方法,又删除了变量
del a        # a.f 的文件操作符消失在了内存中 但是这个文件仍然打开着 类方法__del__执行了关闭文件操作

 

__call__  挺有用的

一个对象后加上括号()相当于执行了__call__方法

class A:
    def __init__(self,name):
        self.name = name
    def __call__(self):
        '''
        打印这个对象中的所有属性
        :return:
        '''
        for k in self.__dict__:
            print(k,self.__dict__[k])
a = A('alex')()

输出:

 

posted @ 2018-12-20 21:31  xyfun72  阅读(171)  评论(0编辑  收藏  举报