码迷,mamicode.com
首页 > 编程语言 > 详细

Python 面向对象进阶

时间:2017-04-25 00:35:38      阅读:326      评论:0      收藏:0      [点我收藏+]

标签:sys   hyper   base   ext1   osi   odi   stat   proc   对象   

 

1 isinstance 和issubclass

instance:判断该对象是否是类的对象

isinstance(obj,Foo)

x = []
print(isinstance(x,list))

结果:
True

issubclass:判断是否是继承


class Foo:
    pass
class Bar(Foo):
    pass
print(issubclass(Bar,Foo))

结果:
True

通过下面的方式也可以查看
print(Bar.base)

2 反射

反射是Smi首次提出的,主要指程序可以访问、检测和修改它本身状态行为的一种能力,也可以叫做自省

2.1面向对象中的反射

面向对象中的反射,是通过字符串形式操作对象的属性,Python中一切都是对象,都可以使用对象

Python中通过hasattr、getattr、setattr、deltattr实现自省的函数,适用于类和对象(一切都是对象)

反射就是把字符串反射成相应的命令

hasattr

查看类和对象中是否有name,用字符串表示,实例在找的时候首先从自身找,自身没有从类找。

class Foo:
    name = ‘aaa‘
f1 =Foo()
print(hasattr(Foo,‘name‘))
print(hasattr(f1,‘name‘))

结果:
True
True

setattr

setattr是设置属性,setattr(x,y,z)

class Foo:
    name = ‘aaa‘
f1 =Foo()

setattr(Foo,‘age‘,18)
print(Foo,‘age‘)
print(f1,‘age‘)

deltattr

print(Foo.__dict__)
delattr(Foo,‘name‘)
print(Foo.__dict__)   
print(hasattr(f1,‘name‘))

结果:
False
通过打印类的名称空间可以查看到name已经没有了

getattr

getattr是查找那个属性,并把命名它的值获得,实际的原理是通过获得字典中的key,然后获得value

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

p = People(‘aaa‘)
print(hasattr(p,‘name‘))
print(‘name‘ in p.__dict__)  # 执行的效果是一样的e

print(hasattr(p,‘country‘))
print(hasattr(People,‘country‘))

print(getattr(p,‘country‘))
print(getattr(p,‘__init__‘))
print(getattr(People,‘country‘))

2.3模块的反射

Python中一切皆对象,模块文件等都是对象

import sys

def s1():
    pass
def s2():
    pass
this_module = sys.modules[__name__]
print(hasattr(this_module,‘s1‘))
print(getattr(this_module,‘s1‘))
  • 结果:
    True

function s1 at 0x00000000005F3E18

3 内置attr

getattr

getattr只有在调用的属性不存在的时候才会触发

class Foo:
    def __init__(self,name):
        self.name = name
    def __getattr__(self, item):
        print("getattr--%s %s"%(item,type(item)))

f = Foo(‘aaa‘)
print(f.xxx)
  • 结果:
    getattr—xxx class ‘str’
    None

setattr

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

class Foo:
    def __init__(self,x):
        self.name=x
    def __setattr__(self, key, value):  # 与上面的对应关系是self--self,name--key,x--value
        self.__dict__[key]=value  # 真正修改的是__dict__中的内容
f1 = Foo(‘aaa‘)
f1.x=‘bbb‘   # 修改属性
f1.age=18  # 增加属性
print(f1.__dict__) # 在名称对象的名称空间中可以显示

deltattr

只有删除属性的时候才会触发deltatr的执行

class Foo:
    def __init__(self,x):
        self.name=x
    def __setattr__(self, key, value):  # 与上面的对应关系是self--self,name--key,x--value
        self.__dict__[key]=value  # 真正修改的是__dict__中的内容
    def __delattr__(self, item):
        self.__dict__.pop(item)
f1=Foo(‘aaa‘)
print(f1.__dict__)
del f1.name
print(f1.__dict__)

结果:
{‘name’: ‘aaa’}
{}

4 反射的应用

4.1 可插拔机制

#客户端
class FtpClient:
    def __init__(self,addr):
        print(‘正在连接服务器[%s]‘%addr)
        self.addr = addr

    def get(self):
        print(‘get‘)

    def test(self):
        print(‘test‘)
#服务端,需要使用客户端的内容
import ftpclient  # 导入test模块(这里是文件)
# f1 = FtpClient(‘192.168.1.1‘)  # wrong
f1=ftpclient.FtpClient(‘192.168.1.1‘)   #这里的对象是文件,即ftpclient,对这个对象进行实例化
if hasattr(f1,‘get‘):  # 首先看是否有这个功能
    func_get=getattr(f1,‘get‘)  # getattr是获得相应的内存地址
    func_get()
else:  # else预语言中是真正的逻辑
    print(‘其他逻辑‘)

4.2 通过字符串导入模块

m = input("输入你要导入的模块")
m1 = __import__(m)
print(m1)
import importlib
t = importlib.import_module(‘time‘)
print(t.time)

5 二次加工标准类型(包装)

Python内部已经有了标准的数据类型和内置方法,但是在很多的情况下,我们需要对数据类型进行自己定制,这几用到了继承和派生的知识

对append添加限制,只能添加数字类型的

class List(list): # List 继承了列表list
    def append(self, p_object):  # 仅仅对append进行修改
        if not isinstance(p_object,int):  # 限制数据类型
            raise TypeError(‘must be int‘)
        super().append(p_object)  # 真正的修改,super是对父类进行修改
l = list([1,2,3])
print(l)
l.append(4)   # 这里是对属性进行修改,实际是对类进行修改
print(l)

结果:
[1, 2, 3]
[1, 2, 3, 4]

上面的情况仅仅是对append进行了修改并添加了限制,list的其他的属性如insert是没有限制的

授权

授权是包装的一个特性,上面的情况是通过继承来实现的,但是函数是不能继承的

授权的过程是所有更新的功能都是由新类的某部分来处理,已经存在的就授权给对象的默认属性

实现授权的关键点就是覆盖getattr方法

import time
class Open:
    def __init__(self,filepath,mode=‘r‘,encoding=‘utf-8‘):
        self.x = open(filepath,mode=mode,encoding=encoding)  # self.x是文件句柄 拿到文件中的内容
        self.filepath=filepath
        self.mode=mode
        self.encoding=encoding
    def write(self,line):  # 在类中新建write功能
        t=time.strftime(‘%Y-%m-%d %X‘)
        self.x.write("%s %s" %(t,line))  # self.x存放的是文件句柄
    def __getattr__(self, item):  # 通过getattr实现的叫做授权
        # print(‘---->‘,item,type(item))  # 测试查看类型
        return getattr(self.x,item)  # 从一个文件对象获得 字符串   现在获得的是self.x 相应方法的地址
f=Open(‘b.txt‘,‘w‘) #实例化一个对象 传入相应的参数
f.write(‘123\n‘)   #Open没有实际的writearttribute

f.write(‘123\n‘)
f.write(‘123\n‘)
f.write(‘123\n‘)
f.write(‘123\n‘)
f.write(‘123\n‘)
f.write(‘123\n‘)

这样就能在文件中添加了带有时间的内容

对文件进行读操作:

f=Open(‘b.txt‘,‘r‘)  # 重新实例化
res = f.read()# f.read实际是self.x 的方法
print(res)
f.seek(0)  #此时光标位于文件的最后
print(f.read())  #这样就可以重新读文件

 

Python 面向对象进阶

标签:sys   hyper   base   ext1   osi   odi   stat   proc   对象   

原文地址:http://www.cnblogs.com/Python666/p/6757870.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!