python之路---面向对象之反射

isinstance() 与 issubclass():

isinstance():用于判断一个对象是否为一个类的实例

python中说一切皆对象,那么我们判断一个变量是否为某个数据类型的时候,就可以使用isinstance()

L = [1,2,3]
print(isinstance(l,list))
#True
#注:L是list这个类的一个实例对象,L=[1,2,3]的本质是L = list([1,2,3])

那么为什么使用isinstance(),而不是最容易想到的type()呢?

1.type() 与isinstance()的判断区别:

   type()不会认为子类是一种父类类型,isinstance()会认为子类是一种父类类型。

class Mylist(list):
    def __init__(self, l):
        super().__init__()
        self.l = l


L = Mylist([1, 2, 3, 4])
print(type(L) is list)
print(isinstance(L, list))
#False
#True
#我们对内置类型(类)进行了扩展,Mylist实例化得到的对象应该也是list类型(它拥有list类产生对象的所有绑#定方法,但是用type()得到的结果却是False)

   此外,新式类与经典类的type(),返回结果不同

Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> class A:pass
...
>>> class B:pass
...
>>> print type(A())
<type 'instance'>
>>> print type(B())
<type 'instance'>
Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:04:45) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> class A:pass
...
>>> class B:pass
...
>>> print(type(A()))
<class '__main__.A'>
>>> print(type(B()))
<class '__main__.B'>

  2.python作为动态语言,在使用的时候不需要声明变量类型,使用type检测特定的类型对象,会破坏代码的灵活性....

issubclass():用于判断一个类是不是另一个类的子类

class People:
    pass

class P(People):
    pass

print(issubclass(P, People))

#True

概念:反射是指程序拥有访问,检测和修改自身状态和行为的一种能力

在python中的反射是指:可以通过字符串去操作对象的相关属性(类本身也是对象)

通过四个函数实现内省:hasattr(),getattr(),delattr(),setattr()


class People:
    country = 'china'

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def func(self):
        print('1')


p = People('bob', 23)
print(People.country) #底层原理实际上是People.__dict__['country']
print(hasattr(p,'name'))  #判断类或对象中有无某个属性(会按照继承查找顺序)
print(getattr(p,'name'))  #第三个参数不指定的情况下,属性不存在会报错
print(getattr(p,'a',None))  #不存在返回None

  此外,用户可以通过input()输入字符串,来反射类内的属性(数据属性与函数属性),从而达到操作对象属性的效果

  在模拟FTP传输中,我们可以根据用户的指令来反射server类中的方法

#settings配置文件
server_address = ('127.0.0.1',8080)


#server端核心层伪代码
import struct
import json
import socketserver
from conf import settings


class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            try:
                header_len = self.request.recv(4)  # 接收报头的长度
                if header_len == 0: break  # 针对linux,客户端单方面退出后发空数据的场景
                header = self.request.recv(struct.unpack('i', header_len)[0]) #接收包含指令信息的报头
                header_dic = json.loads(header.decode('utf-8'))
                if hasattr(self, header_dic['cmd']):
                    func = getattr(self, header_dic['cmd'])
                    func(header_dic)
            except ConnectionResetError:   
                break

    def upload(self,header_dic):
        pass

    def down(self,header_dic):
        pass

    def makdir(self,header_dic):
        pass

    def remove(self,header_dic):
        pass


if __name__ == '__main__':
    obj = socketserver.ThreadingTCPServer \
        (settings.server_address, MyServer, bind_and_activate=True)  # 第三个参数可省略
    obj.serve_forever()  # 相当于建立连接循环

猜你喜欢

转载自blog.csdn.net/ltfdsy/article/details/81977507