首页 > 代码库 > 类 进阶

类 进阶

技术分享

isinstance 和 issubclass

通过例子看:

isinstance

class Foo(object):
    def __init__(self,name,sex):
        self.name=name
        self.sex=sex
    def printer(self):
        print(kkkkkkkkkkkk)
f1=Foo(abc,male)
print(isinstance(f1,Foo))#f1是不是Foo的对象

issubclass

class Foo(object):
    pass
class Bar(Foo):
    pass
print(issubclass(Bar,Foo))  # Bar 是不是Foo 的子类

 

#反射 技术分享

类有属性,对象有属性,只要是通过字符获取的都是反射,在python面向对象中的反射:通过字符的形式操作对象相关的属性python的一切事物都是对象

>>> class Foo(object):
    def __init__(self,name,sex):
        self.name=name
        self.sex=sex
    def printer(self):
        print(kkkkk)

>>> f1=Foo
>>> hasattr(f1,name)  #判断 f1 对象中有没有‘name’这个方法或属性
True

getattr

>>> getattr(f1,sex)    #获取  f1 对象中的‘sex’ 属性或方法
male

>>> getattr(f1,abcd)
Traceback (most recent call last):
  File "<pyshell#19>", line 1, in <module>
    getattr(f1,abcd)
AttributeError: Foo object has no attribute abcd

setattr

>>> setattr(f1,name,david)    #设置   f1  对象中  ‘name‘  方法或属性的值,有则更改为‘david’   ,没有则添加至__dict__字典中
>>> print(f1.name)
david
>>> setattr(f1,age,32)
>>> print(f1.age)
32
>>> print(f1.__dict__)     # 查看对象的数据属性存放
{age: 32, sex: male, name: david}

delattr

>>> delattr(f1,age)   #删除对象的属性值
>>> print(f1.__dict__)
{sex: male, name: david}
>>> delattr(f1,sex)
>>> print(f1.__dict__)
{name: david}

反射当前模块属性:

反射当前模块的属性:
先定义一个类
>>>  class test:
    name=tony
    sex=man
    def __init__(self):
        print(hello)
    def priter(self):
        print(this printer %s%self.sex)
        print(self.name)
>>> this_module=sys.mod 
>>> this_module=sys.modules[__name__]      #这个 __name__  说的是这个模块唯一标识导入系统中的模块



>>> print(this_module)
<module __main__ (built-in)>
>>> hasattr(test,__init__)        #相当于  ‘__init__‘    in  test.__dict__    ,hasattr 做的就是这个事情 
True
>>> p=test()
hello
>>> setattr
<built-in function setattr>   #修改其属性
>>> setattr(p,name,liang)  
>>> print(p.name)
liang

反射的用途:

#两个程序员写一个FTP,Tony,Hua,Tony写程序有些需要用到Hua 所写的类, ,但是Hua 因为有事外出,没有完成要写的类,Tony想到了反射可以继续完成自己的代码,等Hua回来再继续完成类的定义,并且去实现Tony想要的功能。
#反射的好处就是,可以事先定义好接口,接口只有在完成后才会真正执行,这就实现了‘即插即用’,这就是一种‘后期绑定’,就是可以事先把主要的逻辑写好(只定义接口),然后再去实现接口的功能
 
两个文件,一个是ftpserver, 一个是ftpclient ,tony负责Client端的编写,Hua负责Server端的编写
tony没有写完
class FtpCli:
    def __init__(self,addr):
        print(正在连接服务器 [%s] % addr)
        self.addr=addr
 
Hua可以判断tony客户端写了没有,这就用到了反射,如果写了就执行那一部分的代码,如果没有就继续写其它模块:
import FtpClient
f1=FtpClient.FtpCli(192.168.1.1)
# print(f1)
if hasattr(f1,get):  #判断 tony的代码中有没有写get功能。 有则获取运行
    func_get=getattr(f1,get)
    func_get()
else:                 #没有则继续运行其它的代码
    print(other runing)
 
实际应用:二次加工(包装)
#基于继承的原理来定制自己的数据类型
利用反射定制自己的数据类型,如列表、字典,我们可以定制‘值’ 必须是字符串,如:数据库的ID号,必须是int型。那这个时个可以用到“反射”
>>> class List(list):    #定义列表类,继承 python 的list   
    def append(self,value):    #重写它的append方法 
        if not isinstance(value,int):  #判断输入的值是不是 int类型
            raise TypeError(Must be int)   #不是int类型,则举出 ‘必须是int’  的错误
        else:
            super().append(value)   #如果是整型,则使用超类(list)的append方法添加值到列表。    自定义的类是没有append 这些方法的


>>> l1=List([1,2,2,3,4,5,])   #实例化List 类
[1, 2, 2, 3, 4, 5]
>>> l1.append(0)
[1, 2, 2, 3, 4, 5, 0]
>>> l1.append(3) 
Traceback (most recent call last):
  File "<pyshell#106>", line 1, in <module>
    l1.append(3)
  File "<pyshell#100>", line 4, in append
    raise TypeError(Must be int)
TypeError: Must be int    
>>>
 
上面的都理解没有问题:
>>> l1.insert(0,‘fda‘)    这又是怎么回事呢?   这里的insert 不是我们自己定义的List 中的 insert  ,因为没有经过自己定制,那l1就自己执行超类的 insert 方法了。  除非,自己再定制一个 insert  ,再进行一次判断,不能insert 字符串。
>>> l1
[‘fda‘, 1, 2, 2, 3, 4, 5, 0]
 

授权:

不能用继承,实现字典的功能: 字典的值只能是str类型:

#不使用继承  完成字典的数据定制,字典的值必须是int ,

class Dict:
    def __init__(self,key,value):      # 设置值:字典只有key和value
        if not isinstance(value,int):        # 设置 字典的值只能是int 类型
            raise TypeError(must be int)  # 不是int 类型则报出错误
        else:
            self.key=key  #如果是字典类型 则把key的值传进来
        self.c = {key: value} # 初始一个字典,这样就可以限制  健和值了
        self.value = http://www.mamicode.com/value  #值 赋给self.value
    def fu_oprate(self,key,value):     #字典操作 ,也是有键和值
        if not isinstance(value,int):  # 条件判断 传进来的值只能是int ,不是整型则报出错误
            raise TypeError(must be int)  # 报出错误
        if not isinstance(key,str):   #条件判断‘键’ ,只能是字符串类型
            raise TypeError(must be str) #不是字符串类型,报错
        else:
            self.c[key]=value   #如果上述条件都成立,那就将  ‘值‘ 赋给‘键’
            return self.c  #返回整个字典
di1=Dict(name,‘tony’)  #实例化 Dict
print(di1.fu_oprate(age,fifteen))  # 操作字典,这里就已经限制了‘值’的数据类型,这就已经完成自定义数据类型的定制

结果:技术分享

 

完工~~~~~~  技术分享  技术分享 技术分享 技术分享 技术分享 技术分享 技术分享 技术分享 技术分享 技术分享 技术分享 技术分享 技术分享 技术分享

类 进阶