面向对象进阶-反射,内置方法

isinstance和issubclass

isinstance(obj,cls)判断对象所属类型,包括继承关系,     检查obj是不是cls的对象(传两个参数,一个是对象,一个是类)

# class A:pass
# class B(A):pass
# b = B()
# print(isinstance(b,B)) #o,t
# print(isinstance(b,A)) #o,t
# l = list()
# print(l)  # type(l)
# class mystr(str):pass
# ms = mystr('alex')
# print(ms)
# print(type(ms) is str)  # 不包含继承关系,只管一层
# print(isinstance('alex',str)) # 包含所有的继承关系

issubclass(sub, super)判断类与类之间的继承关系, 检查sub是不是super的子类(传两个参数,一个是子类,一个是父类)

# class A:pass
# class B(A):pass
# print(issubclass(B,A))
# print(issubclass(A,B))

反射

反射:可以用字符串的方式去访问对象的属性,调用对象的方法(但是不能去访问方法),python中一切皆对象,都可以使用反射。

反射有四种方法:

hasattr:hasattr(object,name)判断一个对象是否有name属性或者name方法。有就返回True,没有就返回False

getattr:获取对象的属性或者方法,如果存在则打印出来。hasattr和getattr配套使用

    需要注意的是,如果返回的是对象的方法,返回出来的是对象的内存地址,如果需要运行这个方法,可以在后面添加一对()

setattr:给对象的属性赋值,若属性不存在,先创建后赋值

delattr:删除该对象指定的一个属性

 

 1.类  静态属性 类方法 静态方法的反射

# 命名空间.XXX == getattr(命名空间,'XXX')
# class Student:
#     ROLE = 'STUDENT'
#     @classmethod
#     def check_course(cls):
#         print('查看课程了')
#
#     @staticmethod
#     def login():
#         print('登录')
# # 反射查看属性
# # print(Student.ROLE)
# # print(getattr(Student,'ROLE'))
#
# # 反射调用方法
# # getattr(Student,'check_course')()  # 类方法
# # getattr(Student,'login')()         # 静态方法
#
# num = input('>>>')
# if hasattr(Student,num):
#     getattr(Student,num)()
View Code

2.对象 对象属性  方法 的反射

# class A():
#     def __init__(self,name):
#         self.name = name
#
#     def func(self):
#         print('in func')
#
# a = A('alex')
# print(a.name)
# print(getattr(a,'name'))
# getattr(a,'func')()
View Code

3. 模块的反射

# import os   # 别人写好的python代码的结合
# # os.rename('__init__.py','init')
# # getattr(os,'rename')('init','__init__.py') # == os.rename
# rename = os.rename
# rename2 = getattr(os,'rename')
# rename2('__init__.py','init')  # os.rename('__init__.py','init')
# rename('init','init2')          # os.rename('init','init2')
View Code

4.反射自己模块中的内容

# def wahaha():
#     print('wahaha')
#
# def qqxing():
#     print('qqxing')

#
# wahaha()
# qqxing()

# 反射自己模块中的内容  找到自己当前文件所在的命名空间
# import sys
# print(sys.modules)
# import 都相当于导入了一个模块
# 模块哪个导入了 哪个没导入 在我的python解释器里应该记录下来
# import sys 是一个模块,这个模块里的所有的方法都是和python解释器相关的
# sys.modules 这个方法 表示所有在当前这个python程序中导入的模块
# '__main__': <module '__main__' from 'D:/sylar/python_workspace/day20/4.反射.py'>
# print(sys.modules['__main__'])
# my_file = sys.modules['__main__']
# my_file.wahaha()
# my_file.qqxing()
# # 'qqxing'
# # 'wahaha'
# getattr(my_file,'wahaha')()
# getattr(my_file,'qqxing')()
View Code

 

内置方法

__call__

对象后面加括号,触发执行。

注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

# class A:
#     def __call__(self, *args, **kwargs):
#         print('执行call方法了')
#     def call(self):
#         print('执行call方法了')
# class B:
#     def __init__(self,cls):
#         print('在实例化A之前做一些事情')
#         self.a = cls()
#         self.a()
#         print('在实例化A之后做一些事情')
# a = A()
# a()  # 对象() == 相当于调用__call__方法
# a.call()

# A()() # 类名()() ,相当于先实例化得到一个对象,再对对象(),==>和上面的结果一样,相当于调用__call__方法
# B(A)
View Code

__len__

# len(dict)
# len(tuple) str list set
# class mylist:
#     def __init__(self):
#         self.lst = [1,2,3,4,5,6]
#         self.name = 'alex'
#         self.age = 83
#     def __len__(self):
#         print('执行__len__了')
#         return len(self.__dict__)
#
# l = mylist()
# print(len(l))
# len(obj)相当于调用了这个obj的__len__方法
# __len__方法return的值就是len函数的返回值
# 如果一个obj对象没有__len__方法,那么len函数会报错
View Code

__new__    (构造方法和单例模式)

# __new__    # ==> 构造方法
# __init__  # ==> 初始化方法

# class Single:
    # def __new__(cls, *args, **kwargs):
    #     # print('在new方法里')
    #     obj = object.__new__(cls)
    #     print('在new方法里',obj)
    #     return obj

    # def __init__(self):
    #     print('在init方法里',self)

# 1.开辟一个空间,属于对象的
# 2.把对象的空间传给self,执行init
# 3.将这个对象的空间返回给调用者
# obj = Single()
# single的new,single没有,只能调用object的new方法
# new方法在什么时候执行???
    # 在实例化之后,__init__之前先执行new来创建一块空间


# 单例
# 如果一个类 从头到尾只能有一个实例,说明从头到尾之开辟了一块儿属于对象的空间,那么这个类就是一个单例类

# 单例类
class Single:
    __ISINCTANCE = None
    def __new__(cls, *args, **kwargs):
        if not cls.__ISINCTANCE:
            cls.__ISINCTANCE = object.__new__(cls)
        return cls.__ISINCTANCE
    def __init__(self,name,age):
        # self.name = name
        # self.age = age
        print(self)

s1 = Single('alex',83)
s2 = Single('taibai',40)
# print(s1.name)
# print(s2.name)
# print(s1,s2)
View Code

__str__

# __str__
# l = [1,2,3]  # 实例化一个list的对象
# # l是个对象
# print(l)

# class Student:
#     def __str__(self):
#         return '%s %s %s'%(self.school,self.cls,self.name)
#
#     def __init__(self,name,stu_cls):
#         self.school = 'oldboy'
#         self.name = name
#         self.cls = stu_cls
#
# he = Student('hezewei','py14')
# # print(he)
# huang = Student('huangdongyang','py14')
# # print(huang)
# # print(str(he))   # 内置的数据类型,内置的类,相当于执行__str__
# print('学生1 : %s'%he)

# print一个对象相当于调用一个对象的__str__方法
# str(obj),相当于执行obj.__str__方法
# '%s'%obj,相当于执行obj.__str__方法
View Code

__repr__

是__str__的备胎.如果有__str__方法,那么# print %s str都先去执行__str__方法,并且使用__str__的返回值
如果没有__str__,那么 print %s str都会执行repr
repr(obj),%r

# 在子类中使用__str__,先找子类的__str__,没有的话要向上找,只要父类不是object,就执行父类的__str__
# 但是如果出了object之外的父类都没有__str__方法,就执行子类的__repr__方法,如果子类也没有,
# 还要向上继续找父类中的__repr__方法.
# 一直找不到 再执行object类中的__str__方法

# a = '123'
# print(a)
# print(repr(a))

# class A:
#     def __init__(self,name):
#         self.name = name
#     def __str__(self):
#         return '**%s**'%self.name
#     def __repr__(self):
#         return self.name
#
# class B(A):
#     def __init__(self,name):
#         self.name = name
#     def __repr__(self):
#         return '***'
#
# a = B('alex')
# print(a)
# print(str(a),repr(a))
# print('%s | %r'%(a,a))

# print('---%r---'%('abc'))
# print('---%s---'%('abc'))

# __str__ __repr__ : repr
View Code

 __del__

析构方法,释放一个空间之前执行

# 构造方法  申请一个空间
# 析构方法  释放一个空间之前执行
# 某对象借用了操作系统的资源,还要通过析构方法归还回去 : 文件资源  网络资源


# 垃圾回收机制
# class A:
#     def __del__(self):
#         # 析构方法 del A的对象 会自动触发这个方法
#         print('执行我了')
# a = A()
# del a  # 对象的删除 del
# print(a)

# class File():
#     # 处理文件的
#     def __init__(self,file_path):
#         self.f = open(file_path)
#         self.name = 'alex'
#
#     def read(self):
#         self.f.read(1024)
#
#     def __del__(self):   # 是去归还/释放一些在创建对象的时候借用的一些资源
#         # del 对象的时候   程序员触发
#         # python解释器的垃圾回收机制 回收这个对象所占得内存的时候  python自动触发的
#         self.f.close()
# f = File('文件名')
# f.read()
# 不管是主动还是被动,这个f对象总会被清理掉,被清理掉就触发__del__方法,触发这个方法就会归还操作系统的文件资源

# python解释器在内部就能搞定的事儿
# 申请一块儿空间 操作系统分配给你的
# 在这一块儿空间之内的所有事儿 归你的python解释器来管理
# a = 1
# del a
# 对象 --> 内存

# f = open('wenjian')  # python --> 操作系统 --> 硬盘里的文件 --> 文件操作符
# f.close()
# # 文件操作符
# del f
View Code

item系列

__getitem__\__setitem__\__delitem__

# item系列 和对象使用[]访问值有联系
# obj = {'k':'v'}
# print(obj)   # 字典的对象
# print(obj['k'])

# 在内置的模块中,
# 有一些特殊的方法,要求对象必须实现__getitem__/__setitem__才能使用
# class B:
#     def __getitem__(self, item):
#         return getattr(self,item)
#     def __setitem__(self, key, value):
#         setattr(self,key,value*2)
#     def __delitem__(self, key):
#         delattr(self,key)
# b = B()
# # b.k2 = 'v2'
# # print(b.k2)
# b['k1'] = 'v1'  # __setitem__
# print(b['k1'])  # __getitem__
# del b['k1']     # __delitem__
# print(b['k1'])

# class B:
#     def __init__(self,lst):
#         self.lst = lst
#     def __getitem__(self, item):
#         return self.lst[item]
#     def __setitem__(self, key, value):
#         self.lst[key] = value
#     def __delitem__(self, key):
#         self.lst.pop(key)
# b = B(['111','222','ccc','ddd'])
# print(b.lst[0])
# print(b[0])
# b[3] = 'alex'
# print(b.lst)
# del b[2]
# print(b.lst)


# 类
# 每一个对象都是一副扑克牌
# 我想查看这个对象 来查看整副牌

# 我想从这一副牌中随机抽一张牌
# 我想完成打乱这副牌的顺序的功能
View Code

__hash__

# hash方法
# 底层数据结构基于hash值寻址的优化操作
# hash是一个算法
# 能够把某一个要存在内存里的值通过一系列计算,
# 保证不同值的hash结果是不一样的
# '127647862861596'  ==> 927189778748
# 对同一个值在多次执行python代码的时候hash值是不同
# 但是对同一个值 在同一次执行python代码的时候hash值永远不变
# print(hash('abc'))  # 6048279107854451739
# print(hash('abc'))
# print(hash('abc'))
# print(hash('abc'))
# print(hash('abc'))
# print(hash('abc'))

# 字典的寻址  - hash算法
# d = {'key':'value'}
# hash - 内置函数

# set集合
# se = {1,2,2,3,4,5,'a','b','d','f'}
# print(se)

# d = {'key':'v1','key':'v2'}
# print(d['key'])

# hash(obj) #obj内部必须实现了__hash__方法
View Code

__eq__

class A:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __eq__(self, other):
        if self.name == other.name and self.age == other.age:
            return True
a = A('alex',83)
aa = A('alex',83)
aa2 = A('alex',83)
aa3 = A('alex',83)
aa4 = A('alex',83)
aa5 = A('alex',83)
aa6 = A('alex',83)
print(a,aa)
print(aa3 == aa == aa4)  # ==这个语法 是完全和__eq__
View Code

 

 

posted @ 2020-11-02 16:23  断浪狂刀忆年少  阅读(130)  评论(0编辑  收藏  举报