python------面向对象进阶

一、isinstance和issubclass

class A:pass
class B(A):pass
a = A()
print(isinstance(a,A))  # True   a是A的对象
print(issubclass(B,A))  # True    B是A的派生类
print(issubclass(A,B))  # False
# isinstance(obj,cls)检查是否obj是否是类 cls 的对象
# issubclass(sub, super)检查sub类是否是 super 类的派生类
isinstance和issubclass

二、反射

反射:根据字符串的形式去某个对象中操作它的成员
class Person:
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age
    def say(self):
        print('伊娃伊娃哟')
p1 = Person('jim','',20)
print(hasattr(p1,'name')) #判断有木有,有则True,没有False
print(getattr(p1,'sex')) #找不到报错
print(getattr(p1,'age1',22))  #可以设置返回值则不报错

del p1.name    #删除属性方式一
print(p1.__dict__)
delattr(p1,'name')  #删除属性方式二
print(p1.__dict__)

setattr(p1,'name','lucy')  #设置属性值
print(p1.__dict__)
反射函数的用法

 反射的好处:可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,它其实就是一种“后期绑定” 。

       可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能

class FtpClient:
    'ftp客户端,但是还么有实现具体的功能'
    def __init__(self,addr):
        print('正在连接服务器[%s]'%addr)
        self.addr = addr
f1 = FtpClient('192.168.1.1')
if hasattr(f1,'get'):
    func_get = getattr(f1,'get')
    func_get()
else:
    print('---->不存在此方法')
    print('您可以先处理其它逻辑')
class A:
    def func(self):
        print('in func')

a = A()
a.name = 'alex'
a.age = 63
# 反射对象的属性
ret = getattr(a,'name')  # 通过变量名的字符串形式取到的值
# print(ret)
# print(a.__dict__)
# 变量名 = 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')
# 反射类的属性
# A.price
print(getattr(A,'price'))

# 反射类的方法 :classmethod staticmethod
# A.func()
if hasattr(A,'func'):
    getattr(A,'func')()
反射类的属性和方法
#my.py文件
day = 'Monday'  
def wahaha():
    print('wahahaha')
class C:
    pass

#导入my模块
import my   
# 反射模块的属性
print(my.day)   # Monday
print(getattr(my,'day'))  # Monday
# 反射模块的方法
getattr(my,'wahaha')()  # wahahaha
反射模块的属性和方法
import time
print(getattr(time,'time')())  # 1516612064.430534
print(getattr(time,'asctime')())  # Mon Jan 22 17:07:44 2018
内置模块也能用发射
def qqxing():
    print('qqxing')
year = 2018
import sys
# print(sys.modules['__main__'].year)
# 反射自己模块中的变量
print(getattr(sys.modules['__main__'],'year'))  # 2018
# 反射自己模块中的函数
getattr(sys.modules['__main__'],'qqxing')()  # qqxing
变量名 = input('>>>')
print(getattr(sys.modules[__name__],变量名))  # >>>
发射自己模块中的变量和函数

__setattr__ 添加/修改属性时会触发它的执行

__delattr__  删除属性时会触发

__getattr__  只有在使用点调用属性且属性不存在的时候才会触发

系统内置函数属性:若你定义了就用你定义的函数属性,不定义就用系统默认的函数属性

class Foo:
    x = 1
    def __init__(self,y):
        self.y = y
    def __getattr__(self, item):
        print('---->from getattr:你找的属性不存在')
    def __setattr__(self, key, value):
        print('---->from setattr')
        self.__dict__[key] = value
    def __delattr__(self, item):
        print('---->from delattr')
        self.__dict__.pop(item)

# __setattr__添加/修改属性会触发它的执行
f1 = Foo(10)
print(f1.__dict__)  # {'y': 10}
# 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,
# 除非你直接操作属性字典,否则永远无法赋值
f1.z = 3
print(f1.__dict__)  # {'y': 10, 'z': 3}

#__delattr__ 删除属性的时候会触发
f1.__dict__['a'] = 3
print(f1.__dict__)  # {'z': 3, 'y': 10, 'a': 3}
del f1.a
print(f1.__dict__)  # {'z': 3, 'y': 10}

#__getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxx   #---->from getattr:你找的属性不存在
__setattr__、__delattr__、__getattr__

 三、 __str__ 和 __repr__

改变对象的字符串显示__str__, __repr__

自定制格式字符串__format__

# 双下方法
# 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'
nvshen = Teacher('女神',250)
print(nvshen)  # 打印一个对象的时候,就是调用a.__str__
print(repr(nvshen))
print('>>> %r'%nvshen)
#a.__str__ --> object
# object  里有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址

# %s str()  直接打印 实际上都是走的__str__
# %r repr()  实际上都是走的__repr__
# repr 是str的备胎,但str不能做repr的备胎

# print(obj)/'%s'%obj/str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串
# 如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。
# repr(),只会找__repr__,如果没有找父类的
__str__和__repr__
class B:
    def __str__(self):
        return 'str : class B'
    def __repr__(self):
        return 'repr : class B'
b = B()
print('%s' % b)  # str : class B
print('%r' % b)  # repr : class B
%s和%r

四、 __del__

析构方法,当对象在内存中被释放时,自动触发执行

class A:
    def __del__(self):   # 析构函数: 在删除一个对象之前进行一些收尾工作
        print('执行我啦')
        self.f.close()
a = A()
a.f = open('my.py')   # 打开文件 第一 在操作系统中打开了一个文件 拿到了文件操作符存在了内存中
del a          # a.f 拿到了文件操作符消失在了内存中
# del a   # del 既执行了这个方法,又删除了变量
# 引用计数
__del__
class Foo:
    def __del__(self):
        print('执行我啦')
f1 = Foo()
del f1
print('------->')

#输出结果
'''
执行我啦
------->
'''
View Code

五、 __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('jim')()
__call__

六、item系列(__getitem__,__setitem__,__delitem__)

class Foo:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

    def __getitem__(self, item):
        if hasattr(self,item):
            return self.__dict__[item]

    def __setitem__(self, key, value):
        self.__dict__[key] = value

    def __delitem__(self, key):
        del self.__dict__[key]

f = Foo('egon',38,'')
print(f['name'])
f['hobby'] = ''
print(f.hobby,f['hobby'])
# del f.hobby      # object 原生支持  __delattr__
del f['hobby']   # 通过自己实现的
print(f.__dict__)
item系列

七、__new__ 

构造方法 : 创建一个对象

class A:
    def __init__(self):
        self.x = 1
        print('in init function')
    def __new__(cls, *args, **kwargs):
        print('in new function')
        return object.__new__(A, *args, **kwargs)

a1 = A()
#结果
# in new function
# in init function
a2 = A()
#结果
# in new function
# in init function
a3 = A()
#结果
# in new function
# in init function
print(a1)   #<__main__.A object at 0x0000014CC7673B70>
print(a2)   #<__main__.A object at 0x0000014CC7673BA8>
print(a3)   #<__main__.A object at 0x0000014CC7673C18>
print(a1.x)  # 1
View Code
# 单例模式
# 一个类 始终 只有 一个 实例
# 当你第一次实例化这个类的时候 就创建一个实例化的对象
# 当你之后再来实例化的时候 就用之前创建的对象

class A:
    __instance = False
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __new__(cls, *args, **kwargs):
        if cls.__instance:
            return cls.__instance
        cls.__instance = object.__new__(cls)
        return cls.__instance

jim = A('jim',38)
jim.cloth = '小花袄'
lucy = A('lucy',25)
print(lucy)  # <__main__.A object at 0x000002A579843BE0>
print(jim)   # <__main__.A object at 0x000002A579843BE0>
print(lucy.name)  # lucy
print(jim.name)   # lucy
print(lucy.cloth)  # 小花袄
单例模式

八、__eq__

class A:
    def __init__(self,name):
        self.name = name

    def __eq__(self, other):
        if self.__dict__ == other.__dict__:
            return True
        else:
            return False

ob1 = A('jim')
ob2 = A('jim')
ob3 = A('jim1')
print(ob1 == ob2)   # True
print(ob1 == ob3)   # False
View Code

九、__hash__

class A:
    def __init__(self,name,sex):
        self.name = name
        self.sex = sex
    def __hash__(self):
        return hash(self.name+self.sex)

a = A('jim','')
b = A('jim','nv')
print(hash(a))  # -4536380992615375499
print(hash(b))  # -4536380992615375499
View Code

十、__len__

class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __len__(self):
        return len(self.__dict__)
a = A()
print(len(a))   # 2
View Code
原文地址:https://www.cnblogs.com/huangjm263/p/8329834.html