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

Python基础-week06 面向对象编程进阶

时间:2018-08-24 11:47:55      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:是什么   本质   检查   you   属性   提升   派生类   lse   getattr   

一.反射

  1.定义:指的是通过字符串来操作类或者对象的属性

  2.为什么用反射?

    减少冗余代码,提升代码质量。

  3.如何用反射?

    

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


obj=People(jame)


#hasattr
#print(‘country‘ in People.__dict__)
print(hasattr(People,country))

#getattr
#print(People.__dict__[‘country‘])
#print(getattr(People,‘country)) #如果取不到值,会报错。
print(getattr(People,country,None)) #None如果取不到值不报错,返回None


#setattr
#obj.age=18
#print(obj.__dict__)
setattr(obj,age,18)
print(obj.__dict__) #{‘name‘: ‘jame‘, ‘age‘: 18}
setattr(People,x,111)
print(People.__dict__)
#{......, ‘__doc__‘: None, ‘x‘: 111}


#delattr
delattr(People,x)
print(People.__dict__)
#{......, ‘__doc__‘: None}
例1:反射涉及的4个内置函数
技术分享图片
class Ftp:
    def get(self):
        print(get...)


    def put(self):
        print(put...)


    def auth(self):
        print(auth...)



    def run(self):
        while True:
            cmd=input(Please input:).strip() #cmd=‘get
            if hasattr(self,cmd):
                method=getattr(self,cmd)
                method()

            else:
                print(You please input error)



obj=Ftp()
obj.run()
例2:反射的简单使用

 

  动态导入模块<了解>:

  技术分享图片

   

import importlib
 
__import__(import_lib.metaclass) #这是解释器自己内部用的
#importlib.import_module(‘import_lib.metaclass‘) #与上面这句效果一样,官方建议用这个

 

  

二.一些内置方法 和 函数介绍

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

    isinstance(obj,cls)检查是否obj是否是类 cls 的对象。

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

技术分享图片
class Foo(object):
    pass


class bar(Foo):
    pass



obj=Foo()

#1 isinstance判断对象是否属于某类
res1=isinstance(obj,Foo)
print(res1) #True

#2 issubclass 判断bar类是否是 Foo 类的派生类
res2=issubclass(bar,Foo)
print(res2) #true
View Code

 

  2.__setattr__ ,__delattr__ ,__getattr__

   配合反射机制使用,效果还不错. 

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


obj=People(jame)


#hasattr
#print(‘country‘ in People.__dict__)
print(hasattr(People,country))

#getattr
#print(People.__dict__[‘country‘])
#print(getattr(People,‘country123‘)) #如果取不到值,会报错。AttributeError: type object ‘People‘ has no attribute ‘country123‘
print(getattr(People,country123,None)) #None如果取不到值不报错,返回None


#setattr
#obj.age=18
#print(obj.__dict__)
setattr(obj,age,18)
print(obj.__dict__) #{‘name‘: ‘jame‘, ‘age‘: 18}
setattr(People,x,111)
print(People.__dict__)
#{......, ‘__doc__‘: None, ‘x‘: 111}


#delattr
delattr(People,x)
print(People.__dict__)
#{......, ‘__doc__‘: None}
在类外部使用实例 
技术分享图片
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)
        
        

    def __delattr__(self, item):
        print(from delattr)
        self.__dict__.pop(item)



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




#2 __deattr__ 删除属性的时候会触发
#f1.__dict__[‘a‘]=10 #我们可以通过修改属性字典,来完成添加、修改属性的操作
del f1.a #from delattr
print(f1.__dict__) #{‘b‘:4}还剩b



# 3 __getattr__ 只有使用点调用属性且属性不存在的时候才会触发
f1.abc #from getattr:你找的属性不存在.
View Code
技术分享图片
class Ftp:
    def get(self):
        print(get...)


    def put(self):
        print(put...)


    def auth(self):
        print(auth...)



    def run(self):
        while True:
            cmd=input(Please input:).strip() #cmd=‘get
            if hasattr(self,cmd):
                method=getattr(self,cmd)
                method()

            else:
                print(You please input error)



obj=Ftp()
obj.run()
配合反射使用实例

 

   3.__getattribute__

    

技术分享图片
# @Time    : 2018/8/20 17:19
# @Author  : Jame
# class Foo:
#     def __init__(self,x):
#         self.x=x
#
#     def __getattr__(self, item):
#         print(‘执行的是__getattr__‘)
#
#
#
#
# f1=Foo(100)
# print(f1.x)
# f1.xxx #若访问的不存在,则 “执行的是__getattr__”


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

    def __getattribute__(self, item):
        print(不管是否存在都执行的是__getattribute__)


f1=Foo(200)
f1.x
f1.xxx
getattr与getattribute的使用
技术分享图片
class Foo:
    def __init__(self,x):
        self.x=x

    def __getattr__(self, item):
        print(如果不存在则执行__getattr__)

    def __getattribute__(self, item):
        print(不管是否存在都执行的是__getattribute__)
        raise AttributeError(哈哈 嘿嘿 哟哟)


f1=Foo(200)
f1.x
f1.xxx
getattr和getattribute同时存在实例
#当__getattribute__与__getattr__同时存在,只会执行__getattrbute__,除非__getattribute__在执行过程中抛出异常AttributeError

 

  4.描述符(__get__,__set__,__delete__)

    (1).1 描述符是什么?

      描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议
      __get__():调用一个属性时,触发
      __set__():为一个属性赋值时,触发
      __delete__():采用del删除属性时,触发

   

技术分享图片
#1 定义一个描述符
class Foo:
    def __get__(self, instance, owner):
        print(__get__)

    def __set__(self, instance, value):
        print(__set__)

    def __delete__(self, instance):
        print(__delete__)
定义一个描述符

 

 

    (2).描述符是干什么的,何时触发描述符中的3个方法呢?

      描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中__init__())

      包含这三个方法的新式类称为描述符,由这个类产生的实例进行属性的调用/赋值/删除,并不会触发这三个方法!例如:

      

技术分享图片
#2 描述符的使用
class Foo2:
    def __get__(self, instance, owner):
        print(触发 __get__)

    def __set__(self, instance, value):
        print(触发 __set__)

    def __delete__(self, instance):
        print(触发 __delete__)


#包含这三个方法的新式类称为描述符,由这个类产生的实例进行属性的调用/赋值/删除,并不会触发这三个方法!
f2=Foo2()
f2.name=jame
print(f2.name)
del f2.name
描述符的实例进行调用/赋值/删除不会触发

       

      #何地?:定义成另外一个类的类属性

      #何时?:且看下列演示
技术分享图片
class Str:
    def __get__(self, instance, owner):
        print(Str 调用)

    def __set__(self, instance, value):
        print(str 设置)

    def __delete__(self, instance):
        print(str 删除)


class Int:
    def __get__(self, instance, owner):
        print(Int 调用)

    def __set__(self, instance, value):
        print(Int 设置)

    def __delete__(self, instance):
        print(Int 删除)


class People:
    name=Str()
    age=Int()

    def __init__(self,name,age): #name 被设置为Str类的的代理,age被设置Int类的代理。
        self.name=name
        self.age=age


#何地?:定义成另外一个类的类属性

#何时?:且看下列演示

p1=People(jame,18) #触发Str 设置,Int 设置!


#1 描述符str的使用 调用,设置,删除
#p1.name
#p1.name=‘tom‘
#del p1.name
‘‘‘
Str 调用
str 设置
str 删除
‘‘‘

#2 描述符int的使用  调用,设置,删除
#p1.age
#p1.age=30
#del p1.age
‘‘‘
Int 调用
Int 设置
Int 删除
‘‘‘


#3 我们来瞅瞅到底发生了什么?
print(p1.__dict__)
print(People.__dict__)


#补充
print(type(p1) == People) #True,type(p1) 查看p1是哪个类实例化来的。
print(type(p1).__dict__==People.__dict__) #True
触发描述符的场景

 

 

    

    

 

    (3).描述符分两种

      1).数据描述符:至少实现了__get__()和__set__()      

1 class Foo:
2     def __set__(self, instance, value):
3         print(set)
4     def __get__(self, instance, owner):
5         print(get)

 

      2).非数据描述符:没有实现__set__()

  

class Foo:
2     def __get__(self, instance, owner):
3         print(get)

 

  (4).注意事项:
    一 描述符本身应该定义成新式类,被代理的类也应该是新式类
    二 必须把描述符定义成这个类的类属性,不能为定义到构造函数中
    三 要严格遵循该优先级,优先级由高到底分别是
      1.类属性
      2.数据描述符
      3.实例属性
      4.非数据描述符
      5.找不到的属性触发__getattr__()

      。。。。。。

  

三.元类

 

 

四.异常处理

 

Python基础-week06 面向对象编程进阶

标签:是什么   本质   检查   you   属性   提升   派生类   lse   getattr   

原文地址:https://www.cnblogs.com/Jame-mei/p/9507442.html

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