파이썬 반사 / 내장 방법 / 설명자 / 보조 패키징

목차

 

반사

두 가지 내장 기능

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

isinstance (obj, cls)는 obj가 cls 클래스의 객체인지 확인합니다.

2 、 __ setattr __, __ delattr __, __ getattr__

3 、 __ getattribute__

4 、 __ 형식 __

5 、 __ doc__

6 、 __ of__

설명자 3 개 (설명자)

1. 서술자의 본질

2. 설명 자의 역할

3. 예

4. 디스크립터에는 두 가지 유형이 있습니다.

5.주의가 필요한 사항 :

6. 설명 자의 적용

4 차 가공 표준형

꾸러미

__enter__ 및 __exit__ 5 개


반사

파이썬에서는 문자열 형태로 객체의 속성을 조작 할 수 있습니다. 이 동작을 파이썬에서 리플렉션이라고합니다.

문자열을 인스턴스 변수 또는 인스턴스 메서드에 매핑 한 다음 호출 및 수정과 같은 작업을 수행 할 수 있습니다.
다음은 네 가지 기본 반영 방법입니다.

  • getattr 지정된 문자열 이름의 개체 속성을 가져옵니다.이 함수는 속성의 값 또는 메서드의 메모리 주소를 반환합니다.
  • setattr은 객체에 대한 객체를 설정합니다. setattr (x, y, v) 두 번째 매개 변수는 문자열이고 세 번째 매개 변수는 설정할 속성의 값 또는 메소드의 형식입니다.
  • hasattr은 객체에 해당 객체 (문자열)가 있는지 여부를 판단합니다. hasattr (object, name)은 존재하는 경우 True를 반환하고 존재하지 않는 경우 False를 반환합니다.
  • delattr 지정된 속성을 삭제합니다. delattr (x, y) 두 번째 매개 변수는 문자열입니다. 삭제 된 항목이 없으면 오류가보고됩니다.

 사용 범위 :

  1. 개체 및 클래스
  2. 현재 모듈 멤버 반영sys.modules[__name__]  #sys.modules查看所有被导入的模块,以字典的形式存储
  3. 다른 파일 모듈의 반영은 들어오는 모듈을 가져옵니다.

두 가지 내장 기능

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

isinstance (obj, cls)는 obj가 cls 클래스의 객체인지 확인합니다.

class Foo:

    pass

obj = Foo()

print(isinstance(obj,Foo)) #输出结果 True

issubclass (sub, super)는 하위 클래스가 super의 파생 클래스인지 확인합니다.

class Foo(object):

    pass

class Son(Foo):

    pass

print(issubclass(Son,Foo))  #输出结果True

print(issubclass(Foo,object)) #输出结果True

2 、__setattr__,__delattr__,__getattr__

__setattr___ 속성을 추가 / 수정하면 실행이 트리거됩니다.

__delattr___ 속성이 삭제되면 트리거됩니다.

__getattr__포인트를 사용하여 속성이 호출되고 속성이 존재하지 않는 경우에만 트리거되며 기존 속성 또는 메소드가 호출 될 때 트리거되지 않습니다.

class Foo():
​
    def __init__(self,name):
        self.name = name
​
    def func(self):
        print("func------")
​
​
    def __delattr__(self, item):
        print("执行__delattr__")
        # del self.item #无限递归
        self.__dict__.pop(item)
​
    def __setattr__(self, key, value):
        print("执行__setattr__")
        # self.key=value #进入无限递归
        self.__dict__[key]=value #应该使用它
​
p = Foo("jack")  #实例化的过程中会增加属性,执行__setattr__,执行self.__dict__[key]=value语句,为name属性赋值
print(p.name)  #
p.age = 18   #执行__setattr__方法,对象新增加属性
print(p.__dict__)  #输出结果{'name': 'jack', 'age': 18}
del p.age  #调用__delattr__方法,删除对象的age属性
print(p.__dict__) #输出结果{'name': 'jack'},此时已经不包含age属性


输出:
执行__setattr__
jack
执行__setattr__
{'name': 'jack', 'age': 18}
执行__delattr__
{'name': 'jack'}
class Foo():
     def __init__(self,name):
         self.name = name
 ​
     def func(self):
         print("func------")
 ​
     def __getattr__(self, item):
         print("执行__getattr__",item)
 ​
 p = Foo("jack")  #实例化的过程中会增加属性,
 print(p.__dict__)
 print(p.name)
 print(p.age)  #调用不存在的属性会执行__getattr__

输出:
{'name': 'jack'}
jack
执行__getattr__ age
None

삼,__getattribute__

object.__getattribute__(self, name)    무조건 호출되는 인스턴스를 통해 속성에 액세스

인스턴스를 통해 속성에 액세스 할 때마다 __getattribute__함수 를 거치게됩니다 .

속성이 존재하지 않는 경우에도 여전히 액세스해야 __getattribute__하지만 액세스해야합니다 __getattr__. 이것은 예외 처리 기능과 같습니다. 존재하지 않는 변수에 접근하기 위해 클래스를 사용할 때는 __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("不存在的异常")
​
f = Foo("nick")
print(f.x)
print(f.xxxx)#

输出:
执行__getattribute__
None
执行__getattribute__
None

참고 : f.xxxx를 호출 한 후 __getattribute__에서 AttributeError를 생성 한 다음 __getattr__을 호출해야하지만 # 여기서 __getattribute__을 덮어 쓰고 AttributeError가 생성되지 않으므로 __getattr__이 호출되지 않습니다.

즉, __getattr__ 의 호출은 __getattribute__를 통해 AttributeError 예외 생성합니다.

4 、 __ 형식 __

사용자 정의 형식 문자열

format_dic = {
    "ymd":"{0.year}{0.month}{0.day}",
    "dmy":"{0.day}:{0.month}:{0.year}",
    "mdy":"{0.month}-{0.day}-{0.year}"
}
​
class Foo:
​
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day
​
    def __format__(self, format_spec):
        if not format_spec or format_spec not in format_dic:
            format_spec = "ymd"
        fmt = format_dic[format_spec]
        return fmt.format(self)
​
f = Foo(2018,8,20)
print(format(f))
print(format(f,"dmy"))
print(format(f,"mdy"))
print("{:mdy}".format(f))

输出:
2018820
20:8:2018
8-20-2018
8-20-2018

5 、__doc__

class Foo:
    """
    我是文档注释
    """
    pass
​
f = Foo()
print(f.__doc__) #输出结果 :    我是文档注释

6 、__del__

파괴 방법은 객체가 메모리에서 해제 될 때 자동으로 실행을 트리거합니다. 즉, 메모리를 지우고 해제하는 방법입니다.

인스턴스화 된 객체재활용 될 때 실행을 트리거하는 메서드로 객체의 속성을 삭제해도 __del__메서드가 트리거되지 않습니다 .

사용 시나리오 : 1, del obj 2 프로그램이 종료되면 파이썬 인터프리터가 자동으로 메모리를 회수하고 __del__메서드를 실행합니다.

일반적인 애플리케이션 시나리오 :

데이터베이스 클래스를 만들고이 클래스를 사용하여 데이터베이스 링크 개체를 인스턴스화하고 개체 자체는 사용자 공간 메모리에 저장되며 링크는 운영 체제에서 관리되고 커널 공간 메모리에 저장됩니다.

프로그램이 종료되면 파이썬은 자신의 메모리 공간, 즉 사용자 모드 메모리 만 회수하지만 운영 체제의 리소스는 회수되지 않습니다. 이렇게하려면 __del__시스템 호출을 사용자 정의 하고 시작하여 데이터베이스 링크를 닫아야합니다. 개체가 삭제되기 전에 운영 체제., 자원 재활용.

class Foo:
​
    def __del__(self):
        print("我执行了")
​
f = Foo()
f.file  = open("test.txt")   #打开文件,在操作系统中打开了一个文件,
# 拿到了文件操作符存在了内存中
del f.file   #删除了内存中的文件操作符,但是并未关闭操作系统中的文件,
# 这时需要在__del__中加入定制f.file.close(),关闭操作系统的文件
print("-----1")
#最后程序结束python解释器自动执行内存回收,执行了__del__方法

설명자 3 개 ( 설명자 )

( __get__,__set__,__delete__)

파이썬의 설명 자는 객체 속성 작업 (액세스, 할당, 삭제)을위한 프록시 클래스와 같은 자동 실행을 트리거하는 코드를 정의하는 데 사용할 수 있습니다 . 앞에서 설명한 속성은 일종의 설명자입니다.

일반적인 프로세스는 다음과 같습니다.

  1. 하나 이상의 내부 포함 기술자 클래스 D의 정의, __get__(), __set__(), __delete__()방법
  2. 설명자 클래스 D의 인스턴스 객체 d를 프록시 할 다른 클래스의 속성 속성에 할당합니다.attr = D()
  3. 애프터 방문, 할당, 자동 기술자 클래스를 트리거, ATTR 특성을 제거__get__() , __set__(), __delete__()방법

요컨대, 디스크립터 클래스와 인스턴스 객체를 다른 클래스의 속성으로 만드는 것입니다 .

디스크립터 클래스를 정의하는 것은 매우 간단하며, 특정 클래스에 다음과 같은 메소드가 하나 이상 포함되어 있으면 디스크립터 프로토콜을 만족하더라도 디스크립터 클래스이며 속성 연산의 프록시로 사용할 수 있습니다.

것도 유의 하지로 __delete__하고 __del__혼란이 , 전 개체 (종종 지칭 소멸자)의 파괴의 함수 인 프로토콜 서술자를 실현하는 방법이다.

이러한 메서드의 매개 변수에 관계없이 먼저 예제를 살펴 보겠습니다.

class Descriptor():
    def __get__(self, instance, owner):
        print("self: %s\ninstance: %s\nowner: %s" % (self, instance, owner))

class S:
    # 描述符的示例对象作为S的属性
    attr = Descriptor()

s1 = S()
s1.attr  # 访问对象属性

print("-" * 30)
S.attr   # 访问类属性

결과:

self: <__main__.Descriptor object at 0x030C02D0>
instance: <__main__.S object at 0x030C0AB0>
owner: <class '__main__.S'>
------------------------------
self: <__main__.Descriptor object at 0x030C02D0>
instance: None
owner: <class '__main__.S'>

다음 __get__(self, instance, owner)아래에 설명 된 세 가지 매개 변수입니다.

  • self : 프록시 클래스 S의 속성 속성 인 설명자 객체 자체
  • instance : 프록시 클래스의 인스턴스 객체입니다. 따라서 클래스 속성 (class.attr)에 액세스 할 때 없음
  • owner : 설명자 객체가 연결된 클래스, 실제로 인스턴스가 속한 클래스, 즉 type (instance)

여기에서 관련 역할을 설명하십시오.

  • Descriptor: 디스크립터 클래스이자 에이전트이기도합니다.
  • S: 다른 클래스, 관리 클래스, 고객 클래스, 즉 매개 변수의 소유자입니다.
  • attr = Descriptor(): 설명 자의 인스턴스 개체이고 attr은 관리되는 클래스의 특성, 즉 매개 변수의 self입니다.
  • s1: 관리되는 클래스의 인스턴스 개체, 즉 매개 변수의 인스턴스입니다.

1. 서술자의 본질

적어도이 새로운 클래스가 구현하는 새로운 클래스입니다 __get__(), __set__(), __delete__()또한 기술자 프로토콜이라고 그 중 하나는.

__get__(): 속성이 호출 될 때 트리거됩니다.

__set__(): 속성에 값을 할당 할 때 트리거

__delete__(): 속성이 del에 의해 삭제 될 때 트리거됩니다.

2. 설명 자의 역할

다른 클래스의 속성을 프록시하는 데 사용됩니다 ( 설명자는이 클래스의 클래스 속성으로 정의되어야하며 생성자에서 정의 될 수 없음 )

설명자는 다른 클래스의 클래스 속성에 정의되어 있고 설명자는 클래스의 클래스 속성 __dict__사전에 있습니다 .

클래스가 정의하면이 클래스를 설명 자라고 부를 수 있습니다. Owner는 소유자의 클래스이고 instance는 디스크립터에 액세스하는 인스턴스입니다. 인스턴스를 통해 액세스하지 않고 클래스를 통해 액세스하면 인스턴스는 None입니다. ( 자체 액세스하는 디스크립터의 인스턴스는 __get__을 트리거하지 않지만 __call__을 트리거합니다. 다른 클래스의 속성 인 디스크립터 만 의미가 있습니다.)

물론 기술자, 우리는 또한 클래스는 구현하는 경우 알아야 할 __get__()방법을 다음 클래스가 아닌 데이터 기술자라고하며 클래스에서 구현되는 경우 __get__()에도, 그리고 구현 될  __set__()__del__()클래스 데이터 중 하나는 기술자라고

3. 예

클래스를 정의한 후에는 해당 속성에 액세스하고 값을 할당하고 삭제할 수 있습니다. 이러한 작업은 해당 인스턴스 객체에도 적용 할 수 있습니다.

from weakref import WeakKeyDictionary

class Score():
    """ score should in [0,100] """

    def __init__(self):
        self.score = WeakKeyDictionary()
        #self.score = {}

    def __get__(self, instance, owner):
        return self.score[instance]

    def __set__(self, instance, value):
        if 0 <= value <= 100:
            self.score[instance] = value
        else:
            raise ValueError("score not in [0,100]")


class Student():
    # 托管属性定义在类级别上
    score1 = Score()
    score2 = Score()
    score3 = Score()

    def __init__(self, stuid, name, score1, score2, score3):
        self.stuid = stuid
        self.name = name
        self.score1 = score1
        self.score2 = score2
        self.score3 = score3

    def returnMe(self):
        print(self)
        return "%s, %s, %i, %i, %i" % (
            self.stuid,
            self.name,
            self.score1,
            self.score2,
            self.score3)
if __name__=='__main__':
    stu = Student("20101120", "malong", 67, 77, 88)
    print(stu.returnMe())
    # stu.score1 = -23
    print(stu)
    print(type(stu))


输出:
<__main__.Student object at 0x00000285B03FB390>
20101120, malong, 67, 77, 88
<__main__.Student object at 0x00000285B03FB390>
<class '__main__.Student'>

참고 : STU의 정의 후, 자신의 클래스의 예에서 학생 자신이나 스투 스투가 여부, 그렇습니다 기술자 클래스를 유발__get__() , __set__(), __delete__()방법

class Foo:
​
    def __get__(self, instance, owner):
        print("执行了__get__")
​
    def __set__(self, instance, value):
        print("执行了__set__")
​
    def __delete__(self, instance):
        print("执行了__delete__")
​​
class Bar:
    x = Foo()
​
    def __init__(self,name):
        self.name = name
​
​
b = Bar("nick")
b.x     #调用执行描述符里的__get__方法
print(b.x)  #
b.x = 1  # 调用执行描述符里的__set__方法
print(b.__dict__)
del b.x  #调用执行描述符里的__delete__方法
print(b.__dict__)

输出:
执行了__get__
执行了__get__
None
执行了__set__
{'name': 'nick'}
执行了__delete__
{'name': 'nick'}
#描述符Str
class Str:
    def __get__(self, instance, owner):
        print('Str调用')
    def __set__(self, instance, value):
        print('Str设置...')
    def __delete__(self, instance):
        print('Str删除...')
​
#描述符Int
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('alex',18)
​
#描述符Str的使用
p1.name
p1.name='egon'
del p1.name
​
#描述符Int的使用
p1.age
p1.age=18
del p1.age
​
#我们来瞅瞅到底发生了什么
print("__p1.__dict__",p1.__dict__)
print(People.__dict__)
​
#补充
print(type(p1) == People) #type(obj)其实是查看obj是由哪个类实例化来的
print(type(p1).__dict__ == People.__dict__)

输出:
Str设置...
Int设置...
Str调用
Str设置...
Str删除...
Int调用
Int设置...
Int删除...
__p1.__dict__ {}
{'__module__': '__main__', 'name': <__main__.Str object at 0x021C6850>, 'age': <__main__.Int object at 0x021C6870>, '__init__': <function People.__init__ at 0x021C5DB0>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
True
True

참고 : 설명자와 생성자의 이름이 같으면 설명자를 호출합니다.

4. 디스크립터에는 두 가지 유형이 있습니다.

(1) 데이터 설명자 : 최소한 달성 __get__()하고__set__() 

(2) 비 데이터 디스크립터 : 구현되지 않음__set__() 

 참고 : 비 데이터 설명자에는 일반적으로 __get__ 만 있으며 __delete__를 유지하면 오류가보고됩니다.

5.주의가 필요한 사항 :

(1) 설명자 자체는 새로운 스타일의 클래스로 정의되어야하며 프록시되는 클래스는 새로운 스타일의 클래스 여야합니다 (python3의 모든 새로운 스타일의 클래스).

(2) 디스크립터는 다른 클래스의 클래스 속성으로 정의되어야하며 생성자에서 정의 할 수 없습니다.

(3) 우선 순위를 엄격히 준수해야하며, 높은 것부터 낮은 것까지의 우선 순위는

a. 클래스 속성 b. 데이터 설명자 c. 인스턴스 속성 d. 비 데이터 설명자 e. 속성 트리거를 찾을 수 없음__getattr__()

   class Foo:
​
    def __get__(self, instance, owner):
        print("执行了__get__")
​
    def __set__(self, instance, value):
        print("执行了__set__")
​
    def __delete__(self, instance):
        print("执行了__delete__")
​
class People1:
​
    name = Foo()
​
    def __init__(self,name):
        self.name = name

p = People1("nick")        #执行__init__后执行__set__
print(People1.__dict__)    #{'__module__': '__main__', 'name': <__main__.Foo2 object at 0x00000157D73AD208>, '__init__': <function People1.__init__ at 0x00000157D72ED378>, '__dict__': <attribute '__dict__' of 'People1' objects>, '__weakref__': <attribute '__weakref__' of 'People1' objects>, '__doc__': None}
print(People1.name)    # 执行了__get__     None
print(p.__dict__)        #{}
People1.name = "NICK"  # 调用执行了描述符的__set__方法,这一步类属性由之前的描述符被定义成另外一个字符串,
 # 所以下面再次调用就无法再次使用描述符了
print(People1.name)    #NICK
print(p.__dict__)      #{}
print(People1.__dict__)  #{'__module__': '__main__', 'name': 'NICK', '__init__': <function People1.__init__ at 0x00000157D72ED378>, '__dict__': <attribute '__dict__' of 'People1' objects>, '__weakref__': <attribute '__weakref__' of 'People1' objects>, '__doc__': None}

참고 : 클래스 속성의 우선 순위가 데이터 설명자보다 크다는 결론을 내릴 수 있습니다.

class Foo:
​
    def __get__(self, instance, owner):
        print("执行了__get__")
​
    def __set__(self, instance, value):
        print("执行了__set__")
​
    def __delete__(self, instance):
        print("执行了__delete__")
​
class People:
​
    name = Foo()
​
    def __init__(self,name):
        self.name = name
​
​
p = People("nick")  #实例化对象,调用数据描述符的__set__,
# 但是由于描述符的__set__只是执行了打印操作,什么都没做,所以p对象的__dict__什么都没有
p.name = "nicholas"
print(p.__dict__) #输出的结果为空

참고 : 따라서 데이터 설명 자의 우선 순위가 인스턴스 속성 (사전 작업)보다 크다고 결론을 내릴 수 있습니다.

class Foo(object):
    def __init__(self):
        pass
​
    def __get__(self, instance, owner):
        print("执行了__get__")
​
class People(object):
​
    name = Foo("x")
​
    def __init__(self,name,age):
        self.name = name
        self.age = age
​
​
​
p = People("nick",18)  #实例化对象,这里由于是非数据描述符,优先级低于实例属性,
# 所以这里直接设置了实例属性,而不再调用描述符
print(p.name)  #打印直接输出实例属性
print(p.__dict__)
#输出的结果:{'name': 'nick', 'age': 18}

참고 : 따라서 인스턴스 속성의 우선 순위가 비 데이터 설명자보다 크다는 결론을 내릴 수 있습니다.

class Foo(object):
    def __init__(self,name2):
        self.name2 = name2
​
    def __get__(self, instance, owner):
        print("执行了__get__")
​
​
class People(object):
​
    name = Foo("x")
​
    def __init__(self,name,age):
        self.name = name
        self.age = age
​
    def __getattr__(self, item):
        print("__getattr__")
​
​
p = People("nick",18)  #实例化对象,这里由于是非数据描述符,优先级低于实例属性,
# 所以这里直接设置了实例属性,而不再调用描述符
print(p.name)
print(p.sex)  #调用不存在的属性执行了__getattr__
print(p.__dict__)
#输出的结果:{'name': 'nick', 'age': 18}

6. 설명 자의 적용

class Type:
​
    def __init__(self,key,expect_type):
        self.key = key
        self.expect_type = expect_type
​
    def __get__(self, instance, owner):
        print("执行__get__方法")
        print(self)                #这里的self就是type类的对象
        print(instance)            #这里的instance就是传入的People类的对象
        print("执行__get__方法")
        return  instance.__dict__[self.key]   #通过instance的字典获取对象的属性值
​
    def __set__(self, instance, value):
        print("执行__set__方法")
        instance.__dict__[self.key] = value   #instance是另一个类的对象,这里要设置对象的属性字典
​
    def __delete__(self, instance):
        print("执行__delete__方法")
        instance.__dict__.pop(self.key)  #删除对象的属性
​
class People:
    name = Type("name",str)
    age = Type("age",int)
​
    def __init__(self,name,age):
        self.name = name
        self.age = age
​
p1 = People("nick",18)  #调用2次描述符,对对象的字典进行设置
print(p1.name)  #通过数据描述符获取对象的属性值
print(p1.__dict__)
p1.age = 20  #调用描述符对对象进行设置
print(p1.__dict__)

输出:
执行__set__方法
执行__set__方法
执行__get__方法
<__main__.Type object at 0x004CB4F0>
<__main__.People object at 0x02106DF0>
执行__get__方法
nick
{'name': 'nick', 'age': 18}
执行__set__方法
{'name': 'nick', 'age': 20}
class Type:
​
    def __init__(self,key,expect_type):
        self.key = key
        self.expect_type = expect_type
​
    def __get__(self, instance, owner):
        print("执行__get__方法")
        print(self)                #这里的self就是type类的对象
        print(instance)            #这里的instance就是传入的People类的对象
        print("执行__get__方法")
        return  instance.__dict__[self.key]   #通过instance的字典获取对象的属性值
​
    def __set__(self, instance, value):
        print("执行__set__方法")
        if not isinstance(value,self.expect_type):
            print("您输入的%s不是%s"%(self.key,self.expect_type))
            raise TypeError
        instance.__dict__[self.key] = value   #instance是另一个类的对象,这里要设置对象的属性字典
​
    def __delete__(self, instance):
        print("执行__delete__方法")
        instance.__dict__.pop(self.key)  #删除对象的属性
​
class People:
    name = Type("name",str)
    age = Type("age",int)
​
    def __init__(self,name,age):
        self.name = name
        self.age = age
​
p1 = People("nick",18)  #调用2次描述符,对对象的字典进行设置
print(p1.name)  #通过数据描述符获取对象的属性值
print(p1.__dict__)
p1.age = 20  #调用描述符对对象进行设置
print(p1.__dict__)
# p1.name = 11  #通过描述符的if not isinstance(value,self.expect_type)判断属性的类型
​
# p2 = People(88,18)  #通过描述符的if not isinstance(value,self.expect_type)判断属性的类型

4 차 가공 표준형

꾸러미

Python은 표준 데이터 유형과 다양한 내장 메서드를 제공합니다. 실제로 많은 시나리오에서 표준 데이터 유형 및 추가 / 재 작성 방법을 기반으로 자체 데이터 유형을 사용자 정의해야합니다. 이것은 방금 배운 상속을 사용합니다. 파생 된 지식 (다른 표준 유형은 다음과 같은 방식으로 처리 할 수 ​​있음) 간단히 말하면 이전 클래스의 다양한 내장 메서드를 다시 작성하고 원래 함수를 상속 한 다음 함수를 증가시키는 것입니다.

class LIST(list):  #继承list所有的属性
 ​
     def append(self, object):
         if type(object) is not str:  #这里对append方法进行二次处理,增加了新的功能
             print("%s 必须是字符串"%object)
         super().append(object)
         #list.append(self,object) 与上面一句作用相同,都是调用父类list的append方法
 ​
     @property   #使用property使得mid方法更像对象的数据属性,可以直接获得返回值
     def mid(self): #获得列表中间的元素的值
         index = len(self)
         mid_index = index//2  #这里是取除以2的整数商部分,向下取整
         return self[mid_index]
 ​
 ​
 la = LIST("hellonick") #调用list的方法将字符串转为列表
 print(la,type(la)) #输出结果 ['h', 'e', 'l', 'l', 'o', 'n', 'i', 'c', 'k'] <class '__main__.LIST'>
 # 这里的la是类LIST的一个对象
 print(la.mid)  #输出结果 o
 ​
 lb = list("hellonick")
 print(lb,type(lb))  #输出结果['h', 'e', 'l', 'l', 'o', 'n', 'i', 'c', 'k'] <class 'list'>,
 # 这里直接显示lb是列表类型,也是list的一个对象
class LIST(list):  #继承list所有的属性
​
    def __init__(self,item,tag=False):
        super().__init__(item)
        self.tag = tag
​
    def append(self, object):
        if type(object) is not str:  #这里对append方法进行二次处理,增加了新的功能
            print("%s 必须是字符串"%object)
        super().append(object)
        #list.append(self,object) 与上面一句作用相同,都是调用父类list的append方法
​
    def clear(self):
        if not self.tag: #改写原列表方法clear,增加权限限制
            raise PermissionError
        super().clear()
​
la = LIST("hellonick") #调用list的方法将字符串转为列表,输出结果 ['h', 'e', 'l', 'l', 'o', 'n', 'i', 'c', 'k']
print(la)               #['h', 'e', 'l', 'l', 'o', 'n', 'i', 'c', 'k']
print(la.tag)           #False
# la.clear() #会报错
​
​
lb = LIST([2,3,4,5,6,7])
print(lb)                #[2, 3, 4, 5, 6, 7]
# lb.clear() #会报错
print(lb.tag)            #False
​
lc = LIST([5,3,4,5,7],)
lc.tag = True
lc.clear()               
print(lc) #输出结果为 []

승인 : 승인은 패키징의 기능입니다. 유형 패키징은 일반적으로 기존 유형의 일부 사용자 정의입니다.이 접근 방식은 원래 제품의 기능을 생성, 수정 또는 삭제할 수 있습니다. 나머지는 동일하게 유지됩니다. 권한 부여 프로세스는 모든 업데이트 된 함수가 새 클래스의 특정 부분에서 처리되지만 기존 함수는 개체의 기본 속성에 대해 권한이 부여됨을 의미합니다.

간단히 말해서 업데이트 된 함수는 자체 클래스 정의 메서드를 사용하고 업데이트되지 않은 함수는 부모 클래스의 메서드를 사용합니다. 부모 클래스와 이름이 같은 메서드를 정의하는 경우 자신이 정의한 메서드를 사용하고 다른 메서드에 대해 부모 클래스의 메서드를 계속 사용합니다. 인증은 일종의 패키징이지만 인증의 실현은 상속이 아니라 사용 __getattr__방법입니다.

인증을 얻기위한 핵심은 방법 을 재정의하는 __getattr__것입니다.

class FileHandle:
​
    def __init__(self,file,mode,encoding):
        self.file = open(file,mode,encoding=encoding)
​
    def __getattr__(self, item):
        return getattr(self.file,item)
    #这里调用属性的时候自动执行__getattr__方法,执行之后用getattr方法返回原属于open的方法
​
    def read(self):
        print("读取文件中。。。")
    #如果有同名的方法那么就用自己定义的方法,不用__getattr__获得的方法,
    # 因为__getattr__只有在使用点调用属性且属性不存在的时候才会触发
     
​
f = FileHandle("test.txt","w+","utf-8")
f.write("aaaaa")
f.seek(0)
data = f.read()  #这里是执行了FileHandle的自己定义的read()方法,所以输出结果是None
print(data)

 참고 : __getattr__ 함수를 호출 할 때 먼저 클래스에이 함수가 있는지 확인합니다. 그렇다면 클래스의 함수를 호출하고 그렇지 않은 경우 __getattr__을 호출합니다.

 

import time
​
class FileHandle:
​
    def __init__(self,file,mode,encoding):
        self.file = open(file,mode,encoding=encoding)
​
    def __getattr__(self, item):
        return getattr(self.file,item)
    #这里调用属性的时候自动执行__getattr__方法,执行之后用getattr方法返回原属于open的方法
​
    def write(self,msg):
        self.file.write("%s %s"%(time.strftime("%Y-%m-%d %X"),msg))  #调用self.file中open的方法
        #为每次写入增加时间
​
f = FileHandle("test.txt","w+","utf-8")
f.write("aaaaa")
f.seek(0)
data = f.read()
print(data)
 

다섯  __enter____exit__

open ()을 f 작업으로 사용하여 파일 작업을 엽니 다.이를 컨텍스트 관리 프로토콜, 즉 with 문이라고합니다. 개체가 with 문과 호환되도록하려면 개체의 클래스에서 __enter____exit__메서드 를 선언해야합니다 .

__enter__(self): 시작이 실행될 때이 메서드의 작업을 트리거합니다.

__exit__(self, exc_type, exc_val, exc_tb): with 작업이 종료되면이 메서드의 작업을 트리거합니다.

exc_type에서 예외가 발생하면 여기에서 예외 유형을 가져옵니다.

exc_val에서 예외가 발생하면 예외 내용이 여기에 표시됩니다.

exc_tb에서 예외가 발생하면 여기에 위치가 표시됩니다.

 

용도 또는 이점 :

1. with 문을 사용하는 목적은 실행을 위해 코드 블록을 with에 넣는 것입니다. with가 종료되면 수동 개입없이 정리 작업이 자동으로 완료됩니다.

2. 파일, 네트워크 연결 및 잠금과 같은 일부 리소스를 관리해야하는 프로그래밍 환경에서 리소스 __exit__를 자동으로 해제하는 메커니즘을 사용자 지정할 있습니다.이 문제에 대해 더 이상 걱정할 필요가 없으므로 매우 유용합니다.

class OPEN:
 
    def __init__(self,name):
        self.name = name
 
    def __enter__(self):
        print("执行__enter__")
        return self
 
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("执行__exit__")
        print(exc_type)
        print(exc_val)
        print(exc_tb)
        print("执行__exit__2222")
 
with OPEN("a.txt") as f:
    print(f)  #执行打印__enter__内置方法,同时打印内置方法返回的结果
 
#with 语句结束时执行__exit__方法,没有错误则打印None,有错误则打印错误的信息
print("上下文管理协议")

 

추천

출처blog.csdn.net/zangba9624/article/details/109748758