Thư viện python xác thực dữ liệu

Keras được sử dụng bởi CERN, NASA, NIH và nhiều tổ chức khoa học khác trên thế giới (và vâng, Keras được sử dụng tại LHC). Keras có tính linh hoạt cấp thấp để thực hiện các ý tưởng nghiên cứu tùy ý trong khi cung cấp các tính năng tiện lợi cấp cao tùy chọn để tăng tốc chu kỳ thử nghiệm

“Mồi” cung cấp một cái nhìn tổng quan cơ bản, di chuyển nhẹ nhàng từ các ví dụ đơn giản, thêm một tính năng tại một thời điểm. Bắt đầu tại đây nếu bạn chưa quen với bộ mô tả

  • Phần thứ hai hiển thị một ví dụ mô tả thực tế, hoàn chỉnh. Nếu bạn đã biết những điều cơ bản, hãy bắt đầu từ đó

  • Phần thứ ba cung cấp một hướng dẫn kỹ thuật hơn đi sâu vào cơ chế chi tiết về cách hoạt động của bộ mô tả. Hầu hết mọi người không cần mức độ chi tiết này

  • Phần cuối cùng có các từ tương đương Python thuần túy cho các bộ mô tả dựng sẵn được viết bằng C. Hãy đọc phần này nếu bạn tò mò về cách các hàm biến thành các phương thức liên kết hoặc về cách triển khai các công cụ phổ biến như

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    6,
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    7,
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    8 và __slots__ .

  • Lót¶

    Trong phần sơ lược này, chúng tôi bắt đầu với ví dụ cơ bản nhất có thể và sau đó chúng tôi sẽ thêm từng khả năng mới

    ví dụ đơn giản. Một bộ mô tả trả về một hằng số¶

    Lớp

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    9 là một bộ mô tả có phương thức
    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    0 luôn trả về hằng số
    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    1

    class Ten:
        def __get__(self, obj, objtype=None):
            return 10
    

    Để sử dụng bộ mô tả, nó phải được lưu trữ dưới dạng biến lớp trong lớp khác

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    

    Một phiên tương tác cho thấy sự khác biệt giữa tra cứu thuộc tính thông thường và tra cứu bộ mô tả

    ________số 8

    Trong tra cứu thuộc tính

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    2, toán tử dấu chấm tìm thấy
    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    3 trong từ điển lớp. Trong tra cứu
    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    4, toán tử dấu chấm tìm thấy một thể hiện bộ mô tả, được nhận dạng bằng phương thức
    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    5 của nó. Gọi phương thức đó trả về
    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    1

    Lưu ý rằng giá trị

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    1 không được lưu trữ trong từ điển lớp hoặc từ điển cá thể. Thay vào đó, giá trị
    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    1 được tính theo yêu cầu

    Ví dụ này cho thấy cách thức hoạt động của một bộ mô tả đơn giản, nhưng nó không hữu ích lắm. Để truy xuất hằng số, tra cứu thuộc tính thông thường sẽ tốt hơn

    Trong phần tiếp theo, chúng tôi sẽ tạo một thứ hữu ích hơn, một tra cứu động

    Tra cứu động¶

    Các bộ mô tả thú vị thường chạy các phép tính thay vì trả về các hằng số

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    6

    Một phiên tương tác cho thấy rằng tra cứu là động — nó tính toán các câu trả lời khác nhau, được cập nhật mỗi lần

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    7

    Bên cạnh việc chỉ ra cách các bộ mô tả có thể chạy tính toán, ví dụ này cũng tiết lộ mục đích của các tham số đối với

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    0. Tham số tự là kích thước, một thể hiện của DirectorySize. Tham số obj là g hoặc s, một thể hiện của Directory. Đó là tham số obj cho phép phương thức
    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    0 tìm hiểu thư mục đích. Tham số objtype là thư mục lớp

    Thuộc tính được quản lý¶

    Một cách sử dụng phổ biến cho bộ mô tả là quản lý quyền truy cập vào dữ liệu cá thể. Bộ mô tả được gán cho một thuộc tính chung trong từ điển lớp trong khi dữ liệu thực tế được lưu trữ dưới dạng thuộc tính riêng trong từ điển cá thể. Các phương thức

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    0 và
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    12 của bộ mô tả được kích hoạt khi thuộc tính public được truy cập

    Trong ví dụ sau, tuổi là thuộc tính công khai và _age là thuộc tính riêng tư. Khi thuộc tính công khai được truy cập, bộ mô tả ghi nhật ký tra cứu hoặc cập nhật

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    

    Một phiên tương tác cho thấy rằng tất cả quyền truy cập vào tuổi thuộc tính được quản lý đều được ghi lại, nhưng tên thuộc tính thông thường không được ghi lại

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    

    Một vấn đề lớn với ví dụ này là tên riêng _age được cài đặt cố định trong lớp LoggedAgeAccess. Điều đó có nghĩa là mỗi phiên bản chỉ có thể có một thuộc tính đã ghi và tên của thuộc tính đó là không thể thay đổi. Trong ví dụ tiếp theo, chúng tôi sẽ khắc phục sự cố đó

    Tên tùy chỉnh¶

    Khi một lớp sử dụng bộ mô tả, nó có thể thông báo cho từng bộ mô tả về tên biến nào đã được sử dụng

    Trong ví dụ này, lớp

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    13 có hai trường hợp mô tả, tên và tuổi. Khi lớp
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    13 được xác định, nó sẽ gọi lại
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    15 trong LoggedAccess để có thể ghi lại tên trường, cung cấp cho mỗi bộ mô tả public_name và private_name của riêng nó

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    1

    Một phiên tương tác cho thấy lớp

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    13 đã gọi
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    15 để tên trường sẽ được ghi lại. Ở đây chúng tôi gọi
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    18 để tra cứu bộ mô tả mà không kích hoạt nó

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    1

    Lớp mới hiện đăng nhập quyền truy cập vào cả tên và tuổi

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    2

    Hai trường hợp Person chỉ chứa tên riêng

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    0

    Bớt tư tưởng¶

    A mô tả là cái mà chúng tôi gọi là bất kỳ đối tượng nào xác định

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    0,
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    12 hoặc
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    11.

    Tùy chọn, bộ mô tả có thể có phương thức

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    15. Điều này chỉ được sử dụng trong trường hợp bộ mô tả cần biết lớp nơi nó được tạo hoặc tên của biến lớp mà nó được gán cho. (Phương thức này, nếu có, được gọi ngay cả khi lớp không phải là bộ mô tả. )

    Các bộ mô tả được gọi bởi toán tử dấu chấm trong quá trình tra cứu thuộc tính. Nếu một bộ mô tả được truy cập gián tiếp bằng

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    13, thì thể hiện của bộ mô tả được trả về mà không cần gọi nó

    Bộ mô tả chỉ hoạt động khi được sử dụng làm biến lớp. Khi đặt trong các trường hợp, chúng không có tác dụng

    Động lực chính của các bộ mô tả là cung cấp một hook cho phép các đối tượng được lưu trữ trong các biến lớp kiểm soát những gì xảy ra trong quá trình tra cứu thuộc tính

    Theo truyền thống, lớp gọi kiểm soát những gì xảy ra trong quá trình tra cứu. Các bộ mô tả đảo ngược mối quan hệ đó và cho phép dữ liệu được tra cứu có tiếng nói trong vấn đề này

    Mô tả được sử dụng trong toàn bộ ngôn ngữ. Đó là cách các chức năng biến thành các phương thức ràng buộc. Các công cụ phổ biến như

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    6,
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    7,
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    8 và
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    17 đều được triển khai dưới dạng bộ mô tả

    Hoàn thành ví dụ thực tế¶

    Trong ví dụ này, chúng tôi tạo ra một công cụ thiết thực và mạnh mẽ để định vị các lỗi hỏng dữ liệu nổi tiếng là khó tìm

    Lớp trình xác thực¶

    Trình xác thực là một bộ mô tả để truy cập thuộc tính được quản lý. Trước khi lưu trữ bất kỳ dữ liệu nào, nó xác minh rằng giá trị mới đáp ứng các hạn chế về loại và phạm vi khác nhau. Nếu những hạn chế đó không được đáp ứng, nó sẽ tạo ra một ngoại lệ để ngăn chặn tham nhũng dữ liệu tại nguồn của nó

    Lớp

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    18 này vừa là lớp cơ sở trừu tượng vừa là bộ mô tả thuộc tính được quản lý.

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    1

    Trình xác thực tùy chỉnh cần kế thừa từ

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    18 và phải cung cấp phương thức
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    20 để kiểm tra các hạn chế khác nhau khi cần

    Trình xác thực tùy chỉnh¶

    Dưới đây là ba tiện ích xác thực dữ liệu thực tế

    1. import logging
      
      logging.basicConfig(level=logging.INFO)
      
      class LoggedAgeAccess:
      
          def __get__(self, obj, objtype=None):
              value = obj._age
              logging.info('Accessing %r giving %r', 'age', value)
              return value
      
          def __set__(self, obj, value):
              logging.info('Updating %r to %r', 'age', value)
              obj._age = value
      
      class Person:
      
          age = LoggedAgeAccess()             # Descriptor instance
      
          def __init__(self, name, age):
              self.name = name                # Regular instance attribute
              self.age = age                  # Calls __set__()
      
          def birthday(self):
              self.age += 1                   # Calls both __get__() and __set__()
      
      21 xác minh rằng một giá trị là một trong số các tùy chọn bị hạn chế

    2. import logging
      
      logging.basicConfig(level=logging.INFO)
      
      class LoggedAgeAccess:
      
          def __get__(self, obj, objtype=None):
              value = obj._age
              logging.info('Accessing %r giving %r', 'age', value)
              return value
      
          def __set__(self, obj, value):
              logging.info('Updating %r to %r', 'age', value)
              obj._age = value
      
      class Person:
      
          age = LoggedAgeAccess()             # Descriptor instance
      
          def __init__(self, name, age):
              self.name = name                # Regular instance attribute
              self.age = age                  # Calls __set__()
      
          def birthday(self):
              self.age += 1                   # Calls both __get__() and __set__()
      
      22 xác minh rằng một giá trị là một
      import logging
      
      logging.basicConfig(level=logging.INFO)
      
      class LoggedAgeAccess:
      
          def __get__(self, obj, objtype=None):
              value = obj._age
              logging.info('Accessing %r giving %r', 'age', value)
              return value
      
          def __set__(self, obj, value):
              logging.info('Updating %r to %r', 'age', value)
              obj._age = value
      
      class Person:
      
          age = LoggedAgeAccess()             # Descriptor instance
      
          def __init__(self, name, age):
              self.name = name                # Regular instance attribute
              self.age = age                  # Calls __set__()
      
          def birthday(self):
              self.age += 1                   # Calls both __get__() and __set__()
      
      23 hoặc
      import logging
      
      logging.basicConfig(level=logging.INFO)
      
      class LoggedAgeAccess:
      
          def __get__(self, obj, objtype=None):
              value = obj._age
              logging.info('Accessing %r giving %r', 'age', value)
              return value
      
          def __set__(self, obj, value):
              logging.info('Updating %r to %r', 'age', value)
              obj._age = value
      
      class Person:
      
          age = LoggedAgeAccess()             # Descriptor instance
      
          def __init__(self, name, age):
              self.name = name                # Regular instance attribute
              self.age = age                  # Calls __set__()
      
          def birthday(self):
              self.age += 1                   # Calls both __get__() and __set__()
      
      24. Theo tùy chọn, nó xác minh rằng một giá trị nằm trong khoảng tối thiểu hoặc tối đa nhất định

    3. import logging
      
      logging.basicConfig(level=logging.INFO)
      
      class LoggedAgeAccess:
      
          def __get__(self, obj, objtype=None):
              value = obj._age
              logging.info('Accessing %r giving %r', 'age', value)
              return value
      
          def __set__(self, obj, value):
              logging.info('Updating %r to %r', 'age', value)
              obj._age = value
      
      class Person:
      
          age = LoggedAgeAccess()             # Descriptor instance
      
          def __init__(self, name, age):
              self.name = name                # Regular instance attribute
              self.age = age                  # Calls __set__()
      
          def birthday(self):
              self.age += 1                   # Calls both __get__() and __set__()
      
      25 xác minh rằng một giá trị là một
      import logging
      
      logging.basicConfig(level=logging.INFO)
      
      class LoggedAgeAccess:
      
          def __get__(self, obj, objtype=None):
              value = obj._age
              logging.info('Accessing %r giving %r', 'age', value)
              return value
      
          def __set__(self, obj, value):
              logging.info('Updating %r to %r', 'age', value)
              obj._age = value
      
      class Person:
      
          age = LoggedAgeAccess()             # Descriptor instance
      
          def __init__(self, name, age):
              self.name = name                # Regular instance attribute
              self.age = age                  # Calls __set__()
      
          def birthday(self):
              self.age += 1                   # Calls both __get__() and __set__()
      
      26. Theo tùy chọn, nó xác nhận độ dài tối thiểu hoặc tối đa nhất định. Nó cũng có thể xác thực một biến vị ngữ do người dùng định nghĩa

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    2

    Ứng dụng thực tế¶

    Đây là cách trình xác thực dữ liệu có thể được sử dụng trong một lớp thực

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    3

    Các bộ mô tả ngăn không cho các trường hợp không hợp lệ được tạo

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    4

    Hướng dẫn kỹ thuật¶

    Phần tiếp theo là hướng dẫn kỹ thuật hơn về cơ học và chi tiết về cách thức hoạt động của bộ mô tả

    Trừu tượng¶

    Xác định các bộ mô tả, tóm tắt giao thức và chỉ ra cách các bộ mô tả được gọi. Cung cấp một ví dụ cho thấy cách ánh xạ quan hệ đối tượng hoạt động

    Tìm hiểu về các bộ mô tả không chỉ cung cấp quyền truy cập vào bộ công cụ lớn hơn mà còn tạo ra sự hiểu biết sâu sắc hơn về cách thức hoạt động của Python

    Định nghĩa và giới thiệu¶

    Nói chung, bộ mô tả là một giá trị thuộc tính có một trong các phương thức trong giao thức bộ mô tả. Các phương thức đó là

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    0,
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    12 và
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    11. Nếu bất kỳ phương thức nào trong số đó được xác định cho một thuộc tính, thì nó được gọi là mô tả .

    Hành vi mặc định để truy cập thuộc tính là lấy, đặt hoặc xóa thuộc tính khỏi từ điển của đối tượng. Chẳng hạn,

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    2 có một chuỗi tra cứu bắt đầu bằng
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    01, sau đó là
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    02 và tiếp tục thông qua thứ tự giải quyết phương pháp của
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    03. Nếu giá trị tra cứu là một đối tượng xác định một trong các phương thức mô tả, thì Python có thể ghi đè hành vi mặc định và gọi phương thức mô tả thay thế. Điều này xảy ra ở đâu trong chuỗi ưu tiên phụ thuộc vào phương pháp mô tả nào được xác định

    Bộ mô tả là một giao thức có mục đích chung, mạnh mẽ. Chúng là cơ chế đằng sau các thuộc tính, phương thức, phương thức tĩnh, phương thức lớp và

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    04. Chúng được sử dụng xuyên suốt Python. Bộ mô tả đơn giản hóa mã C cơ bản và cung cấp một bộ công cụ mới linh hoạt cho các chương trình Python hàng ngày

    Giao thức mô tả¶

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    05

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    06

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    07

    Đó là tất cả để có nó. Xác định bất kỳ phương thức nào trong số này và một đối tượng được coi là bộ mô tả và có thể ghi đè hành vi mặc định khi được tra cứu dưới dạng thuộc tính

    Nếu một đối tượng định nghĩa

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    12 hoặc
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    11, nó được coi là một bộ mô tả dữ liệu. Bộ mô tả chỉ xác định
    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    0 được gọi là bộ mô tả phi dữ liệu (chúng thường được sử dụng cho các phương thức nhưng có thể sử dụng cho các mục đích khác)

    Các bộ mô tả dữ liệu và phi dữ liệu khác nhau về cách tính các giá trị ghi đè đối với các mục nhập trong từ điển của một cá thể. Nếu từ điển của một cá thể có một mục nhập có cùng tên với một bộ mô tả dữ liệu, thì bộ mô tả dữ liệu đó sẽ được ưu tiên. Nếu từ điển của một cá thể có một mục nhập có cùng tên với một bộ mô tả phi dữ liệu, thì mục nhập trong từ điển đó sẽ được ưu tiên

    Để tạo bộ mô tả dữ liệu chỉ đọc, hãy xác định cả

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    0 và
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    12 với
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    12 nâng cao một
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    14 khi được gọi. Xác định phương thức
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    12 với một trình giữ chỗ nâng cao ngoại lệ là đủ để biến nó thành một bộ mô tả dữ liệu

    Tổng quan về lời gọi bộ mô tả¶

    Một bộ mô tả có thể được gọi trực tiếp với

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    16 hoặc
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    17

    Nhưng điều phổ biến hơn là một bộ mô tả được gọi tự động từ quyền truy cập thuộc tính

    Biểu thức

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    18 tra cứu thuộc tính
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    19 trong chuỗi không gian tên cho
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    20. Nếu tìm kiếm tìm thấy một bộ mô tả bên ngoài thực thể
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    21, thì phương thức
    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    0 của nó được gọi theo các quy tắc ưu tiên được liệt kê bên dưới

    Các chi tiết của lời gọi phụ thuộc vào việc

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    20 là một đối tượng, lớp hay thể hiện của super

    Gọi từ một thể hiện¶

    Tra cứu phiên bản quét qua một chuỗi các không gian tên ưu tiên cao nhất cho các bộ mô tả dữ liệu, tiếp theo là các biến thể hiện, sau đó là các bộ mô tả không phải dữ liệu, sau đó là các biến lớp và cuối cùng là

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    24 nếu nó được cung cấp

    Nếu một bộ mô tả được tìm thấy cho

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    2, thì nó được gọi với.
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    26

    Logic cho một tra cứu chấm là trong

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    27. Đây là một Python thuần túy tương đương

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    5

    Lưu ý, không có móc

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    24 trong mã
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    29. Đó là lý do tại sao gọi trực tiếp
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    29 hoặc với
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    31 sẽ bỏ qua hoàn toàn
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    24

    Thay vào đó, nó là toán tử dấu chấm và hàm

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    33 chịu trách nhiệm gọi
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    24 bất cứ khi nào
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    29 tăng một
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    14. Logic của chúng được gói gọn trong một hàm trợ giúp

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    6

    Lời gọi từ một lớp¶

    Logic cho tra cứu chấm, chẳng hạn như

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    37 nằm trong
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    38. Các bước tương tự như đối với
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    27 nhưng tra cứu từ điển cá thể được thay thế bằng tìm kiếm thông qua thứ tự giải quyết phương thức của lớp.

    Nếu một bộ mô tả được tìm thấy, nó sẽ được gọi bằng

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    40

    Việc thực hiện C đầy đủ có thể được tìm thấy trong

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    41 và
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    42 trong Objects/typeobject. c

    Lời gọi từ super¶

    Logic cho tra cứu chấm của super nằm trong phương thức

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    29 cho đối tượng được trả về bởi
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    04

    Một tra cứu chấm, chẳng hạn như

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    45 tìm kiếm
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    46 cho lớp cơ sở
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    47 ngay sau
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    48 và sau đó trả về
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    49. Nếu không phải là một bộ mô tả,
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    50 được trả về không thay đổi

    Việc thực hiện C đầy đủ có thể được tìm thấy trong

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    51 trong Objects/typeobject. c. Có thể tìm thấy một Python thuần túy tương đương trong Hướng dẫn của Guido

    Tóm tắt logic lời gọi¶

    Cơ chế cho bộ mô tả được nhúng trong các phương thức

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    29 cho
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    53,
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    54 và
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    04

    Những điểm quan trọng cần nhớ là

    • Các mô tả được gọi bằng phương thức

      class A:
          x = 5                       # Regular class attribute
          y = Ten()                   # Descriptor instance
      
      29

    • Các lớp kế thừa bộ máy này từ

      class A:
          x = 5                       # Regular class attribute
          y = Ten()                   # Descriptor instance
      
      53,
      class A:
          x = 5                       # Regular class attribute
          y = Ten()                   # Descriptor instance
      
      54 hoặc
      class A:
          x = 5                       # Regular class attribute
          y = Ten()                   # Descriptor instance
      
      04

    • Ghi đè

      class A:
          x = 5                       # Regular class attribute
          y = Ten()                   # Descriptor instance
      
      29 ngăn các lệnh gọi bộ mô tả tự động vì tất cả logic của bộ mô tả đều nằm trong phương thức đó

    • class A:
          x = 5                       # Regular class attribute
          y = Ten()                   # Descriptor instance
      
      27 và
      class A:
          x = 5                       # Regular class attribute
          y = Ten()                   # Descriptor instance
      
      38 thực hiện các cuộc gọi khác nhau tới
      >>> mary = Person('Mary M', 30)         # The initial age update is logged
      INFO:root:Updating 'age' to 30
      >>> dave = Person('David D', 40)
      INFO:root:Updating 'age' to 40
      
      >>> vars(mary)                          # The actual data is in a private attribute
      {'name': 'Mary M', '_age': 30}
      >>> vars(dave)
      {'name': 'David D', '_age': 40}
      
      >>> mary.age                            # Access the data and log the lookup
      INFO:root:Accessing 'age' giving 30
      30
      >>> mary.birthday()                     # Updates are logged as well
      INFO:root:Accessing 'age' giving 30
      INFO:root:Updating 'age' to 31
      
      >>> dave.name                           # Regular attribute lookup isn't logged
      'David D'
      >>> dave.age                            # Only the managed attribute is logged
      INFO:root:Accessing 'age' giving 40
      40
      
      0. Cái đầu tiên bao gồm thể hiện và có thể bao gồm lớp. Ví dụ thứ hai đặt vào
      class A:
          x = 5                       # Regular class attribute
          y = Ten()                   # Descriptor instance
      
      64 và luôn bao gồm lớp

    • Bộ mô tả dữ liệu luôn ghi đè từ điển cá thể

    • Bộ mô tả phi dữ liệu có thể bị từ điển cá thể ghi đè

    Thông báo tên tự động¶

    Đôi khi bộ mô tả mong muốn biết nó được gán cho tên biến lớp nào. Khi một lớp mới được tạo, siêu dữ liệu

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    54 sẽ quét từ điển của lớp mới. Nếu bất kỳ mục nào là bộ mô tả và nếu chúng xác định
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    15, thì phương thức đó được gọi với hai đối số. Chủ sở hữu là lớp mà bộ mô tả được sử dụng và tên là biến lớp mà bộ mô tả được gán cho

    Chi tiết triển khai có trong

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    67 và
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    68 trong Objects/typeobject. c

    Vì logic cập nhật là trong

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    69, thông báo chỉ diễn ra tại thời điểm tạo lớp. Nếu các bộ mô tả được thêm vào lớp sau đó, thì
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    15 sẽ cần được gọi thủ công

    Ví dụ về ORM¶

    Đoạn mã sau là một khung đơn giản hóa cho thấy cách sử dụng bộ mô tả dữ liệu để triển khai ánh xạ quan hệ đối tượng

    Ý tưởng cơ bản là dữ liệu được lưu trữ trong cơ sở dữ liệu bên ngoài. Các phiên bản Python chỉ giữ các khóa cho các bảng của cơ sở dữ liệu. Bộ mô tả chăm sóc tra cứu hoặc cập nhật

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    7

    Chúng ta có thể sử dụng lớp

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    71 để định nghĩa các mô hình mô tả lược đồ cho từng bảng trong cơ sở dữ liệu

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    8

    Để sử dụng các mô hình, trước tiên hãy kết nối với cơ sở dữ liệu

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    9

    Một phiên tương tác cho biết cách truy xuất dữ liệu từ cơ sở dữ liệu và cách cập nhật dữ liệu đó

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    0

    Tương đương Python thuần túy¶

    Giao thức mô tả đơn giản và cung cấp các khả năng thú vị. Một số trường hợp sử dụng phổ biến đến mức chúng đã được đóng gói sẵn thành các công cụ tích hợp. Các thuộc tính, phương thức liên kết, phương thức tĩnh, phương thức lớp và __slots__ đều dựa trên giao thức mô tả

    Đặc tính¶

    Gọi

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    8 là một cách ngắn gọn để xây dựng bộ mô tả dữ liệu kích hoạt lệnh gọi hàm khi truy cập vào một thuộc tính. Chữ ký của nó là

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    1

    Tài liệu cho thấy cách sử dụng điển hình để xác định thuộc tính được quản lý

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    19

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    2

    Để xem cách

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    8 được triển khai theo giao thức mô tả, đây là một Python thuần túy tương đương

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    3

    Nội dung dựng sẵn

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    8 trợ giúp bất cứ khi nào giao diện người dùng đã cấp quyền truy cập thuộc tính và sau đó các thay đổi tiếp theo yêu cầu sự can thiệp của một phương thức

    Chẳng hạn, một lớp bảng tính có thể cấp quyền truy cập vào một giá trị ô thông qua

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    76. Những cải tiến tiếp theo của chương trình yêu cầu tính toán lại ô trên mỗi lần truy cập; . Giải pháp là bọc quyền truy cập vào thuộc tính giá trị trong bộ mô tả dữ liệu thuộc tính

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    4

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    8 tích hợp sẵn hoặc tương đương với
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    78 của chúng tôi sẽ hoạt động trong ví dụ này

    Hàm và phương thức¶

    Các tính năng hướng đối tượng của Python được xây dựng dựa trên môi trường dựa trên chức năng. Sử dụng các bộ mô tả phi dữ liệu, cả hai được hợp nhất liền mạch

    Các hàm được lưu trữ trong từ điển lớp được chuyển thành các phương thức khi được gọi. Các phương thức chỉ khác với các hàm thông thường ở chỗ thể hiện đối tượng được thêm vào trước các đối số khác. Theo quy ước, thể hiện được gọi là self nhưng có thể được gọi là this hoặc bất kỳ tên biến nào khác

    Các phương thức có thể được tạo thủ công với

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    79 tương đương với

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    5

    Để hỗ trợ tạo phương thức tự động, các chức năng bao gồm phương thức

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    0 cho các phương thức liên kết trong quá trình truy cập thuộc tính. Điều này có nghĩa là các hàm là bộ mô tả phi dữ liệu trả về các phương thức bị ràng buộc trong quá trình tra cứu theo dấu chấm từ một thể hiện. Đây là cách nó hoạt động

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    6

    Chạy lớp sau trong trình thông dịch cho biết cách hoạt động của bộ mô tả hàm trong thực tế

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    7

    Hàm có thuộc tính tên đủ điều kiện để hỗ trợ xem xét nội quan.

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    8

    Truy cập chức năng thông qua từ điển lớp không gọi

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    0. Thay vào đó, nó chỉ trả về đối tượng hàm bên dưới

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    9

    Truy cập chấm từ một lớp gọi

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    0 chỉ trả về chức năng cơ bản không thay đổi

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    60

    Hành vi thú vị xảy ra trong quá trình truy cập chấm từ một phiên bản. Tra cứu dấu chấm gọi

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    0 trả về một đối tượng phương thức bị ràng buộc

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    61

    Bên trong, phương thức ràng buộc lưu trữ chức năng cơ bản và thể hiện bị ràng buộc

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    62

    Nếu bạn đã từng thắc mắc self đến từ đâu trong các phương thức thông thường hoặc cls đến từ đâu trong các phương thức lớp, thì đây chính là

    Các loại phương pháp¶

    Các bộ mô tả phi dữ liệu cung cấp một cơ chế đơn giản cho các biến thể trên các mẫu chức năng liên kết thông thường thành các phương thức

    Tóm lại, các hàm có một phương thức

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40
    
    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}
    
    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31
    
    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40
    
    0 để chúng có thể được chuyển đổi thành một phương thức khi được truy cập dưới dạng thuộc tính. Bộ mô tả phi dữ liệu chuyển đổi một cuộc gọi
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    85 thành
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    86. Gọi
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    87 trở thành
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    88

    Biểu đồ này tóm tắt ràng buộc và hai biến thể hữu ích nhất của nó

    chuyển đổi

    Được gọi từ một đối tượng

    Được gọi từ một lớp

    hàm số

    f(obj, *args)

    f(*args)

    phương pháp tĩnh

    f(*args)

    f(*args)

    phương pháp phân loại

    f(loại(obj), *args)

    f(cls, *args)

    Phương thức tĩnh¶

    Các phương thức tĩnh trả về hàm cơ bản mà không thay đổi. Gọi

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    89 hoặc
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    90 tương đương với việc tra cứu trực tiếp vào
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    91 hoặc
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    92. Kết quả là, chức năng trở nên có thể truy cập giống hệt nhau từ một đối tượng hoặc một lớp

    Ứng cử viên sáng giá cho các phương thức tĩnh là các phương thức không tham chiếu đến biến

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    93

    Chẳng hạn, gói thống kê có thể bao gồm lớp chứa dữ liệu thử nghiệm. Lớp này cung cấp các phương thức thông thường để tính toán số liệu thống kê trung bình, trung bình, trung bình và các số liệu thống kê mô tả khác phụ thuộc vào dữ liệu. Tuy nhiên, có thể có các chức năng hữu ích liên quan đến khái niệm nhưng không phụ thuộc vào dữ liệu. Chẳng hạn,

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    94 là thói quen chuyển đổi tiện dụng xuất hiện trong công việc thống kê nhưng không phụ thuộc trực tiếp vào một tập dữ liệu cụ thể. Nó có thể được gọi từ một đối tượng hoặc lớp.
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    95 hoặc
    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    96

    Vì các phương thức tĩnh trả về hàm cơ bản mà không có thay đổi nào, nên các lệnh gọi ví dụ không thú vị

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    63

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    64

    Sử dụng giao thức mô tả phi dữ liệu, một phiên bản Python thuần túy của

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    7 sẽ trông như thế này

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    65

    Phương thức lớp¶

    Không giống như các phương thức tĩnh, các phương thức lớp thêm tham chiếu lớp vào danh sách đối số trước khi gọi hàm. Định dạng này giống nhau cho dù người gọi là một đối tượng hay một lớp

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    66

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    67

    Hành vi này hữu ích bất cứ khi nào phương thức chỉ cần có một tham chiếu lớp và không phụ thuộc vào dữ liệu được lưu trữ trong một thể hiện cụ thể. Một cách sử dụng cho các phương thức lớp là tạo các hàm tạo lớp thay thế. Ví dụ: classmethod

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    98 tạo một từ điển mới từ danh sách các khóa. Tương đương Python thuần túy là

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    68

    Giờ đây, một từ điển mới về các khóa duy nhất có thể được xây dựng như thế này

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    69

    Sử dụng giao thức mô tả phi dữ liệu, một phiên bản Python thuần túy của

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    6 sẽ trông như thế này

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    70

    Đường dẫn mã cho

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    00 đã được thêm vào Python 3. 9 và cho phép
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    6 hỗ trợ các nhà trang trí chuỗi. Ví dụ: một phương thức lớp và thuộc tính có thể được kết nối với nhau. Trong Trăn 3. 11, chức năng này không được dùng nữa

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    71

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    72

    đối tượng thành viên và __slots__¶

    Khi một lớp định nghĩa

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    02, nó sẽ thay thế các từ điển mẫu bằng một mảng các giá trị vị trí có độ dài cố định. Từ quan điểm của người dùng có một số tác dụng

    1. Cung cấp khả năng phát hiện lỗi ngay lập tức do gán thuộc tính sai chính tả. Chỉ cho phép các tên thuộc tính được chỉ định trong

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    02

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    73

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    74

    2. Giúp tạo các đối tượng bất biến trong đó các bộ mô tả quản lý quyền truy cập vào các thuộc tính riêng tư được lưu trữ trong

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    02

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    75

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    76

    3. Tiết kiệm bộ nhớ. Trên bản dựng Linux 64 bit, một phiên bản có hai thuộc tính chiếm 48 byte với

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    02 và 152 byte không có. Mẫu thiết kế flyweight này có thể chỉ quan trọng khi một số lượng lớn các phiên bản sẽ được tạo

    4. Cải thiện tốc độ. Đọc các biến thể hiện nhanh hơn 35% với

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    02 (được đo bằng Python 3. 10 trên bộ xử lý Apple M1)

    5. Chặn các công cụ như

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    17 yêu cầu từ điển phiên bản hoạt động chính xác

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    77

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    78

    Không thể tạo phiên bản Python thuần túy thả xuống chính xác của

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    02 vì nó yêu cầu quyền truy cập trực tiếp vào cấu trúc C và kiểm soát phân bổ bộ nhớ đối tượng. Tuy nhiên, chúng ta có thể xây dựng một mô phỏng gần như trung thực trong đó cấu trúc C thực tế cho các vị trí được mô phỏng bằng danh sách
    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    09 riêng tư. Việc đọc và ghi vào cấu trúc riêng tư đó được quản lý bởi các bộ mô tả thành viên

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    79

    Phương thức

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance
    
    69 đảm nhiệm việc thêm các đối tượng thành viên vào các biến lớp

    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class LoggedAgeAccess:
    
        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value
    
        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value
    
    class Person:
    
        age = LoggedAgeAccess()             # Descriptor instance
    
        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()
    
        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()
    
    0

    Phương thức

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10
    
    11 đảm nhiệm việc tạo các phiên bản có vị trí thay vì từ điển phiên bản. Đây là một mô phỏng sơ bộ trong Python thuần túy