首页 > 代码库 > python篇1.12---面向对象进阶

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

一.isinstance(obj,cls) 和 issubclass(sub,super)

 

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

class Foo(object):
    pass

obj = Foo()

print(isinstance(obj,Foo))

 

2.issubclass(sub,super)检查sub类 是否是 super类的 派生类

class Foo(object):
    pass

class Bar(Foo):
    pass

print(issubclass(Bar,Foo))

 


 二.反射

1.神马反射

  反射的概念是由 Smith在1982年首次提出的,主要是指程序可以访问,检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

 

2.python 面向对象中的反射:通过字符串的形式操作对象相关的属性。Python中的一切事物都是对象(都可以使用反射)

 

四个可以 实现 自省的函数:

1.hasattr(obj,name):判断object中有没有一个name字符串对应的方法或属性

技术分享
#hasattr

class People:
    country = China
    def __init__(self,name):
        self.name = name

p = People(egon)

print(p.__dict__)
print(name in p.__dict__)   #验证 ‘name‘ 是否存在

print(hasattr(p,name))  #使用 hasattr 验证‘name‘是否存在 !!!
print(hasattr(p,name1213))     # 不在
hasattr

 

2.getattr(object, name, default=None)

技术分享
#### ---->getattr
class People:
    country = China
    def __init__(self,name):
        self.name = name
    def walk(self):
        print({} is walking.format(self.name))

p = People(egon)

res = getattr(p,country)  # 相当于res = p.country
print(res)


f = getattr(p,walk)   #相当于 f = p.walk
 print(f)


f1 = getattr(People,walk)
print(f1)


# f()
# f1(p)
getattr

 

技术分享
class People:
    country = China
    def __init__(self,name):
        self.name = name
    def walk(self):
        print({} is walking.format(self.name))

p = People(egon)

# print(p.xxxx)  #会报错
print(getattr(p,xxxx,这个属性确实不存在))

if hasattr(p,walk):
    func = getattr(p,walk)
    func()    #运行结果:egon is walking

 

3.setattr(x,y,z)

技术分享
class People:
    country = China
    def __init__(self,name):
        self.name = name
    def walk(self):
        print({} is walking.format(self.name))

p = People(egon)


##setattr
p.sex = male
print(p.sex)
print(p.__dict__)

##运行结果
##male
##{‘name‘: ‘egon‘, ‘sex‘: ‘male‘}
setattr

 

4.delattr(x,y)

技术分享
##delattr

class People:
    country = China
    def __init__(self,name):
        self.name = name
    def walk(self):
        print({} is walking.format(self.name))

p = People(egon)

# print(p.__dict__)
# del p.name          #使用的 del
# print(p.__dict__)


print(p.__dict__)  #使用 delattr !!!
delattr(p,name)
print(p.__dict__)


##运行结果
##{‘name‘: ‘egon‘}
##{}
delattr

 

#四个方法的使用演示

技术分享
class BlackMedium:
    feature = Ugly     #特性 = 邪恶
    def __init__(self,name,addr):
        self.name = name
        self.addr = addr

    def sell_house(self):
        print({} 黑中介买房子啦,傻逼才买呢,但是谁能不证明自己不傻逼.format(self.name))
    def rent_house(self):
        print({} 黑中介租房子啦,傻逼才租呢.format(self.name))

b1 = BlackMedium(万成置地,回龙观天露园)


#检测是否含有属性
print(hasattr(b1,name))         #Ture
print(hasattr(b1,sell_house))
print(hasattr(b1,rent_house))


#获取属性
n = getattr(b1,name)
print(n)

f = getattr(b1,rent_house)
f()
f1 = getattr(b1,sell_house)
f1()

getattr(b1,aaaaa)  #会报错
print(getattr(b1,aaaaa,不存在!!!))



#设置属性
setattr(b1,sb,True)
setattr(b1,show_name,显示名字)  #原码(b1,‘show_name‘,lambda self:self.name+‘sb‘)
print(b1.__dict__)
# print(b1.show_name(b1))



#删除属性            #设置属性的代码,打开状态,可进行此步
delattr(b1,addr)
delattr(b1,show_name)
# delattr(b1,‘show_name33333‘)  #不存在会报错

print(b1.__dict__)
View Code

 

 ##类也是对象

技术分享
class Foo(object):
    staticField = old boy

    def __init__(self):
        self.name = wupeiqi

    def func(self):
        return func

    @staticmethod
    def bar():
        return bar

print(getattr(Foo,staticField))
print(getattr(Foo,func))
print(getattr(Foo,bar))


##输出结果
old boy
<function Foo.func at 0x01723588>
<function Foo.bar at 0x017234B0>
View Code

 

#反射当前模块成员

技术分享
import sys

def s1():
    print(s1)

def s2():
    print(s2)

this_module = sys.modules[__name__]

print(hasattr(this_module, s1))
print(getattr(this_module, s2))


##输出结果
True
<function s2 at 0x02D734B0>
View Code

 

 

反射的用途

技术分享
##未用反射

import sys

def add():
    print(add)

def change():
    print(change)

def search():
    print(search)


def delete():
    print(delete)

func_dic={
    add:add,
    change:change,
    search:search,
    delete:delete
}


while True:
    cmd=input(>>:).strip()
    
    if not cmd:continue
    
    if cmd in func_dic:     #hasattr()
        
        func=func_dic.get(cmd)  #func=getattr()
        
        func()
未用反射

 

技术分享使用反射

 

 

通过字符串导入模块

技术分享
##第一种方法
# m=input("请输入你要导入的模块:")

# m1=__import__(m)
# print(m1)
# print(m1.time())


##运行
##请输入你要导入的模块:time
##<module ‘time‘ (built-in)>
##1493031349.9390879


##第二种方法 (推荐使用方法)!!!
import importlib
t=importlib.import_module(time)
print(t.time())
View Code

 

 


 

 三.attr系列:__setattr__,__getattr__,__delattr__

a.

技术分享
#__setattr__,__getattr__,__delattr__,


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

    def __setattr__(self, key, value):

        # if not isinstance(value,str):
        #     raise TypeError(‘must be str‘)
        # print(‘----setattr---key:%s,value:%s‘ %(key,value))
        # print(type(key))
        # print(type(value))
        # self.key=value
        # setattr(self,key_str,value) #self.key_attribute=value

        self.__dict__[key]=value

    def __delattr__(self, item):
        
        print(delattr:---》{}.format(item))
        print(type(item))

        # delattr(self,item)
        # del self.item

        self.__dict__.pop(item)


f1=Foo(egon) #f1.name=‘egon‘

f1.age=18

# print(f1.__dict__)
# print(f1.name)
# print(f1.age)

##后续操作
print(f1.__dict__)
del f1.age
print(f1.__dict__)
# print(f1.age)   #执行会报错  
View Code

 

b.

技术分享
class Foo:
    def __init__(self,x):
        self.name=x

    #属性不存在的情况下才会触发
    def __getattr__(self, item):
        print(getattr-->{}  {}.format(item,type(item)))


f=Foo(egon)
# print(f.name)

print(f.kkkkk)
View Code

 

 


 

四.item系列:__setiem__,__getitem__,__delitem__

技术分享
#把对象操作属性模拟成字典的格式

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

    def __getitem__(self,item):
        #print(‘getitem‘,item)
        return self.__dict__[item]

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

    def __delitem__(self,key):
        self.__dict__.pop(key)

    # def __delattr__(self,item):
    #     print(‘del obj.key时,我执行‘)
    #     self.__dict__.pop(item)

f = Foo(egon)

# print(f.name)


f.name = egonlin   #更改 name= ’egon‘为 ‘egonlin
f[age] = 18
print(f.__dict__)


##进行 del 操作
del f[age]
print(f.__dict__)



# print(f[‘name‘])
View Code

 

 


 

 

五.__slots__

技术分享
‘‘‘
1.__slots__是什么:是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性)

2.引子:使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例的是独立的)
3.为何使用__slots__:字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__
当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个
字典,这跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是我们不能再给
实例添加新的属性了,只能使用在__slots__中定义的那些属性名。
4.注意事项:__slots__的很多特性都依赖于普通的基于字典的实现。另外,定义了__slots__后的类不再 支持一些普通类特性了,比如多继承。大多数情况下,你应该
只在那些经常被使用到 的用作数据结构的类上定义__slots__比如在程序中需要创建某个类的几百万个实例对象 。
关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。           更多的是用来作为一个内存优化工具。

‘‘‘


class Foo:
    __slots__ = x

f1 = Foo()

f1.x = 1
# f1.y = 2   #报错

print(f1.__slots__)




class Bar:
    __slots__ = [x,y]


n = Bar()

n.x,n.y = 1,2
# n.z = 3    #会报错,原本没 z的存在

print(n.__slots__)
__slots__使用
技术分享
class People:
    __slots__=[x,y,z]

p=People()
print(People.__dict__)

p.x=1
p.y=2
p.z=3
print(p.x,p.y,p.z)
# print(p.__dict__)    #报错

p1=People()
p1.x=10
p1.y=20
p1.z=30
print(p1.x,p1.y,p1.z)
#print(p1.__dict__)  报错
例二

 

技术分享
class Foo:
    __slots__ = [name,age]


f1 = Foo()
f1.name = alex
f1.age = 18
print(f1.__slots__)


f2 = Foo()
f2.name = egon
f2.age = 20
print(f1.__slots__)


print(Foo.__dict__)
#f1 与f2 都没有属性字典__dict__了,统一归__slots__管,节省内存
刨根问底

 

 


 

六.__call__

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

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

 

技术分享
class Foo:
    def __init__(self):
        pass

    def __call__(self,*args,**kwargs):
        print(__call__)


obj = Foo()        #执行__init__
obj()              #执行__call__


##输出结果
__call__
例一

 

技术分享
class People:
    def __init__(self,name):
        self.name=name

    def __call__(self, *args, **kwargs):
        print(call)


p=People(egon)

print(callable(People))
print(callable(p))

p()



#输出结果
True
True
call
例二

 

 


 

七.实现迭代器协议

1.for(无限循环)

技术分享
from collections import Iterable,Iterator

class Foo:
    def __init__(self,start):
        self.start = start

    def __iter__(self):
        return self

    def __next__(self):
        return aSB

f = Foo(0)
# f.__iter__()
# f.__next__()
#
# print(isinstance(f,Iterable))
# print(isinstance(f,Iterator))    #是否是 迭代器
#
#
# print(next(f))    #相当于print(f.__next__())
# print(next(f))
# print(next(f))


for i in f:
    print(i)
View Code

 

2.for(有限)

技术分享
rom collections import Iterable,Iterator

class Foo:
    def __init__(self,start):
        self.start=start

    def __iter__(self):
        return self

    def __next__(self):
        if self.start > 10:
            raise StopIteration
        n=self.start
        self.start+=1
        return n


f=Foo(0)


for i in f:
    print(--->,i)
View Code

 

3.for 循环 range

技术分享
class Range:
    123
    def __init__(self,start,end):
        self.start=start
        self.end=end

    def __iter__(self):
        return self

    def __next__(self):
        if self.start == self.end:
            raise StopIteration
        n=self.start
        self.start+=1
        return n

for i in Range(0,5):
    print(i)


# print(Range.__doc__)
View Code

 

 


 

八.__doc__, 加 __module__,__class__

技术分享
class Foo:
    我是描述信息
    pass

class Bar(Foo):
    pass
print(Bar.__doc__) #该属性无法继承给子类


b=Bar()
print(b.__class__)
print(b.__module__)
print(Foo.__module__)


print(Foo.__class__)
View Code

 


 

九.__del__ (析构函数)

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

注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

 

技术分享
class Foo:
    def __del__(self):
        print(执行我了)

f1 = Foo()

# del f1

print(----->)


##输出结果
----->
执行我了
简单示范

 

 

技术分享
class Foo:
    def __del__(self):
        print(执行我了)

f1 = Foo()

del f1        # 此步的 存在!!!

print(----->)


##执行结果

执行我了
----->
挖坑埋了你

 

 

技术分享
import time
class Open:
    def __init__(self,filepath,mode=r,encode=utf-8):
        self.f=open(filepath,mode=mode,encoding=encode)

    def write(self):
        pass

    def __getattr__(self, item):
        return getattr(self.f,item)

    def __del__(self):
        print(----->del)
        self.f.close()

f=Open(a.txt,w)


print(======>>>)
##输出结果

##======>>>
##----->del






import time
class Open:
    def __init__(self,filepath,mode=r,encode=utf-8):
        self.f=open(filepath,mode=mode,encoding=encode)

    def write(self):
        pass

    def __getattr__(self, item):
        return getattr(self.f,item)

    def __del__(self):
        print(----->del)
        self.f.close()


f = Open(a.txt,w)

del f            #  此步的存在 !!!!!!

print(=======>>>)


#输出结果

----->del
=======>>>
扩大版

 

 


 

metaclass(元类)

1.引子

class Foo:
    pass

f1 = Foo()   #f1是通过Foo类实例化的对象

 

  Python中的一切皆是对象,类本身也是一个对象,当使用关键字class的时候,python解释  器在加载class的时候就会创建一个对象(这里的对象指的是类而非类的实例)

 

上例可以看出f1是由 Foo这个类产生的对象,而Foo本身也是对象,那他又是由哪个类产生的呢?

#type函数可以查看类型,也可以用来查看对象的类,二者是一样的
 print(type(f1)) # 输出:<class ‘__main__.Foo‘>     表示,obj 对象由Foo类创建
print(type(Foo)) # 输出:<type ‘type‘>  

 

2.什么是元类?

元类是类的类,是类的模板

元类是用来控制如何创建类的,正如类是创建对象的模板一样

元类的实例为类,正如类的实例为对象(f1d对象是Foo的一个实例,Foo类是type类的一个实例)

type是python的一个内建元素,用来直接控制生成类,python中class定义的类其实都是type类实例化的对象

 

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