面向对象进阶

一.isinstance和issubclass

1.身份运算

print(type(2) == int)  #True
print(type(2) is int) #True

2.对象与类之间的关系 isinstance

isinstance(obj,cls)判断obj是否是类 cls 的对象 包括继承的判断
class A:pass
class B(A):pass
b=B()
print(isinstance(b,B)) #True
print(isinstance(b,A)) #True

3.类与类之间的关系  issubclass(A,B)

issubclass(A,B) 判断第一个参数疑似子类,第二个参数疑似父类。第一个必须是子类
class A:pass
class B(A):pass
print(issubclass(B,A)) #Trueer

二、反射

1.反射的定义:通过字符串来操作python代码中的变量,函数甚至方法和类

hasattr  判断某一个 变量 是否能够.调用一个名字,返回True或者False
getattr 直接获取一个变量中的名字的值
setattr 为一个变量增加或者修改一个属性
delattr 删除一个变量中的属性或者方法

2.值=getattr(类名,字符串类型的属性名) 如果第二个参数是不存在的属性名则会报错
hasattr判断属性名是否存在 hasattr常与getattr

class A:
    name="alex"
    age=18
tag=input("<<<:")
if tag=="name":print(A.name)
if tag=="age":print(A.age)
#利用反射实现上述功能
print(getattr(A,tag))
2.获取方法
class A:
   def __init__(self,name,age):
       self.name=name
       self.age=age
   def show(self):
        for key in self.__dict__:
            print(key,self.__dict__[key])
alex=A("alex",18)
if hasattr(alex,"show"):
    func=getattr(alex,"show")  #得到的是内存地址
    func()
View Code

3.##setattr设置和修改属性###

class A:
def __init__(self,name):
self.name=name
alex=A("alex")
setattr(alex,'sex',"man") #增加
print(alex.sex)
setattr(alex,'name',"jerd") #修改
print(alex.name) #jerd

4.###delattr删除属性###

class A:
    def __init__(self,name):
        self.name=name
alex=A("alex")
print(alex.name) #alex
delattr(alex,'name')
print(alex.name) #AttributeError: 'A' object has no attribute 'name'
View Code

5.##'__main__'和__name__##

def sww():
    print("爽歪歪")
count=0
###在my__moudle文件中写入
# money=100
# count=1
# import d27w6
# def sww():
#     print("爽歪歪")
import sys
print(sys.modules['__main__'])  #<module '__main__' from 'D:/lianxi/python/数据类型和函数/d27w6.py'>
如果在另一个文件中导入了当前文件,执行另一个文件会显示另一个文件名的名字
执行my__moudle文件 <module '__main__' from 'D:/lianxi/python/数据类型和函数/my_moudle.py'>
print(sys.modules[__name__])  在另一个文件中也会显示当前文件的名字
print(getattr(sys.modules[__name__],"count")) 两个文件中均显示0
print(getattr(sys.modules['__main__'],"count")) #当前文件显示0  my__moudle文件显示1
View Code

6.反射类 可以进行实例化

import sys
main=sys.modules[__name__]
class A:
    count=1
    def __init__(self,name,age):
        self.name=name
        self.age=age
cls=getattr(main,'A')
stduent=cls("alex",18)  ##进行实例化
print(stduent.__dict__)
View Code

反射知识点总结

1.反射类中的名字
getattr(类名,'静态属性')
getattr(类名,'类方法')()
getattr(类名,'静态方法')()
2.反射对象中的名字
getattr(对象名,'对象属性')
getattr(对象名,'方法名')()
3.反射模块中的名字
import 模块名
getattr(模块名,'模块中的变量')
getattr(模块名,'模块中的函数')()
getattr(模块名,'模块中的类名')
4.反射当前模块中的名字
import sys
getattr(sys.modules[__name__],'变量')
getattr(sys.modules[__name__],'函数')()
getattr(sys.modules[__name__],'类名')
5.反射类 
import sys
main=sys.modules[__name__]
class A:pass
cls=getattr(main,'A')
View Code

三.类中的内置方法

1.类中的内置方法(又称魔术方法 双下方法)会自动调用 __方法名__ 如__len(obj)__
是直接和python的语法隐形相关

2.__len__方法

如果类中不写def __len__(self)这个方法,会报错,在类中光兵没有len这个方法
#写的话,就自动调用了__len__这个方法,就像在实例化时会自动调用__init__方法
class A:
    def __init__(self,name,sex):
        self.name = name
        self.sex = sex
    def __len__(self):
        return len(self.__dict__)
hei = A('小黑','')
print(len(hei))  #2
View Code

3.__eq__方法


class A:
    def __init__(self,name,sex):
        self.name = name
        self.sex = sex
hei = A('小黑','')
hei2= A('小黑','')
print(hei.__dict__)  #{'name': '小黑', 'sex': ''}
print(hei2.__dict__)  #{'name': '小黑', 'sex': ''}
print(hei == hei2) #False    在类中 == 实际上是默认比较内存地址的
###修改默认##
class A:
    def __init__(self,name,sex):
        self.name = name
        self.sex = sex
    def __eq__(self, other):
        if self.__dict__ == other.__dict__:
            return True
hei = A('小黑','')
hei2= A('小黑','')
print(hei == hei2)  #True 自动调用__eq__
View Code

4.__format__


format_dict={
    'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
    'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
    'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
}
class School:
    def __init__(self,name,addr,type):
        self.name=name
        self.addr=addr
        self.type=type
    def __format__(self,format_spec):
        return format_spec.format(obj=self)
s1=School('oldboy1','北京','私立')
print(format(s1,format_dict['tna']))
print(format(s1,'tna'))
View Code

5.__str__ 返回值必须是字符串,否则抛出异常

class School:
    def __init__(self,name,addr,type):
        self.name=name
        self.addr=addr
        self.type=type
    def __str__(self):
        return str(self.__dict__)
s1=School('oldboy1','北京','私立')
print(str(s1))  #{'name': 'oldboy1', 'addr': '北京', 'type': '私立'}
print('%s'%s1) #{'name': 'oldboy1', 'addr': '北京', 'type': '私立'}
print(s1)      直接调用了__str__#{'name': 'oldboy1', 'addr': '北京', 'type': '私立'}
View Code

6.__repr__ 返回值必须是字符串,否则抛出异常

class School:
    def __init__(self,name,addr,type):
        self.name=name
        self.addr=addr
        self.type=type
    def __repr__(self):  # repr是str的备胎
        return 'repr : school的repr对象'
s1=School('oldboy1','北京','私立')
print(repr(s1))  #repr : school的repr对象
print('%r'%s1)  直接调用了__repr__#repr : school的repr对象
View Code

7.__repr__是__str__的备胎。在不存在__str__的情况下print(str(s1))会自动调用__repr__


class School:
    def __init__(self,name,addr,type):
        self.name=name
        self.addr=addr
        self.type=type
    # def __str__(self):
    #     return str(self.__dict__)
    def __repr__(self):  # repr是str的备胎
        return 'repr : school的repr对象'
s1=School('oldboy1','北京','私立')
print(str(s1))  #repr : school的repr对象
print(repr(s1))  #repr : school的repr对象
View Code


 
 
 
 
 
 
原文地址:https://www.cnblogs.com/zgf-666/p/8551745.html