Python Dynamic properties and features (ii)

Source: Internet
Author: User

The built-in property is often used as an adorner, but it is actually a class. In Python, functions and classes are usually interchangeable, because both are callable objects, and there are no instantiated new operators, so there is no difference between calling a constructor method and calling a factory function, as long as the new callable object can be returned instead of the decorated function, both of which can be used as adorners

The full signature of the property initialization method (__INIT__) is as follows:

Property (Fget=none, Fset=none, Fdel=none, Doc=none)

All parameters are optional, and if the function is not passed to a parameter, the resulting attribute object is not allowed to perform the corresponding operation

Class LineItem:    def __init__ (self, description, weight, price):        self.description = Description        Self.weight = weight        Self.price = Price    def subtotal (self):        return self.weight * self.price    def get_ Weight (self):  # <1>        return self.__weight    def set_weight (self, value):  # <2>        If Value > 0:            self.__weight = value        else:            raise ValueError (' value must is > 0 ')    Weight = Property ( Get_weight, Set_weight)  # <3>

  

    1. Common method of Reading value
    2. Common method of setting values
    3. Building the Property object and assigning it to the exposed class properties

Test LineItem This class

line = LineItem ("Golden raisins", ten, 6.5) print ("<1>:", Line.subtotal ())  # <1>line.weight = 9

  

Operation Result:

<1>: 65.0Traceback (most recent): ... Valueerror:value must be > 0

  

Of course, we can write another form, and it is also possible to read and set the public properties by means of the

Class LineItem:    def __init__ (self, description, weight, price):        self.description = Description        Self.weight = weight        Self.price = Price    def subtotal (self):        return self.weight * self.price    @property C7/>def Weight:        return self.__weight    @weight. Setter    def weight (self, value):        if value > 0:            Self.__weight = value        else:            raise ValueError (' value must be > 0 ')

  

Attributes are class properties, but attribute management is actually access to instance properties, and if the instance and the owning class have properties of the same name, the instance properties override the Class property when getting the instance Read property

Class class:    data = "The class data attr"    @property    def prop (self):        return "The prop value" obj = Class () pr int ("<1>:", VARs (obj))  # <1>print ("<2>:", Obj.data)  # <2>obj.data = "Bar"  # <3 >print ("<4>:", VARs (obj))  # <4>print ("<5>:", Obj.data)  # <5>print ("<6>:", Class.data)  # <6>

  

Operation Result:

<1>: {}<2>: the class data attr<4>: {' data ': ' Bar '}<5>: bar<6>: the class data attr

  

    1. VARs () returns the Obj.__dict__ property, indicating that the instance has no attributes
    2. Read Obj.data, get the value of Class.data
    3. Assign a value to Obj.data, create an attribute for the instance
    4. View the instance's properties again with VARs ()
    5. Now read Obj.data, instance properties override class properties
    6. Print class Properties Class.data

Below, try overriding the prop attribute of obj

Print ("<1>:", Class.prop)  # <1>print ("<2>:", Obj.prop)  # <2>obj.prop = "Hello World"

    

Operation Result:

<1>: <property object at 0x00000000004805e8><2>,: the prop Valuetraceback (most recent call last):    o Bj.prop = "Hello world" Attributeerror:can ' t set attribute

  

    1. Read the prop attribute directly from class, get the attribute object itself, do not run the Read value method of the attribute
    2. Read Obj.prop performs an attribute reading method
    3. Attempt to set pro instance properties, result failed
obj.__dict__["prop"] = "Hello World"  # <1>print ("<2>:", VARs (obj))  # <2>print ("<3>:" , Obj.prop)  # <3>class.prop = "Baz"  # <4>print ("<5>:", Obj.prop)  # <5>

  

Operation Result:

<2>: {' prop ': ' Hello World '}<3>: the prop value<5>: Hello World

  

    1. The previous example throws an exception by setting Obj.prop, so we try to set the instance properties through obj.__dict__
    2. You can see that the previous step was set successfully
    3. However, the read-value method of the attribute is still run when reading prop, and the attribute is not overwritten by the instance property
    4. Override Class.prop Properties, destroy Property objects
    5. Now, Obj.prop reads the instance properties. Class.prop is not an attribute, so it will no longer overwrite Obj.prop

Defining an attribute Factory function

We will define an attribute function called quantity, which is required to manage the two properties of weight and price before lineitem in this class, requiring both properties to be greater than 0

Def quantity (Storage_name):    def qty_getter (instance):  # <3>        return Instance.__dict__[storage_ Name]    def qty_setter (instance, value):  # <4>        if value > 0:            instance.__dict__[storage_name] = Value        else:            raise ValueError (' value must is > 0 ')    return property (Qty_getter, Qty_setter) class LineItem :    weight = quantity (' weight ')  # <1> Price    = Quantity ("Price")    def __init__ (self, Description, weight, price):        self.description = description        self.weight = weight  # <2>        Self.price = Price    def subtotal (self):        return self.weight * self.price

    

    1. Use the factory function to define weight and price as class properties
    2. Here, the feature is activated to ensure that weight cannot be set to negative or 0
    3. The first argument of the Qty_getter function can be named self, but it is strange because the Qty_getter function is not in the definition body of the class, instance refers to the LineItem instance, in Qty_getter, from the LineItem instance of __ Dict__ gets the desired property, and then returns
    4. Define the Qty_setter function, the first parameter instance is also the LineItem instance, and then the value is stored in instance.__dict__, which is also to skip the feature to avoid recursive loop last stack Overflow

Test Factory functions

Nutmeg = LineItem ("Moluccan nutmeg", 8, 13.95) print ("<1>:", Nutmeg.weight, Nutmeg.price)  # <1>print (" <2>: ", Sorted (VARs (nutmeg). Items ())  # <2>

  

Operation Result:

<1>: 8 13.95<2>: [(' Description ', ' Moluccan nutmeg '), (' Price ', 13.95), (' Weight ', 8)]

  

When defining an attribute, you can use the @attr.deleter adorner to wrap a method that is responsible for deleting attribute-managed properties

Class BlackKnight:    def __init__ (self):        self.members = [' An arm ', ' another arm ',                        ' a leg ', ' another leg ']        self.phrases = ["' Tis but a scratch.",                        "It's Just a flesh wound.", "                        I ' m invincible!", "All right                        , we'll call I T a draw. "]    @property    def member (self):        print (' Next member is: ')        return self.members[0]    @member. deleter    def member (self):        text = ' BLACK KNIGHT (loses {}) \n--{} '        print (Text.format (self.members.pop (0), Self.phrases.pop (0)))

  

Test Delete attribute

b = BlackKnight () del B.memberdel B.memberdel B.memberdel b.member

  

Operation Result:

BLACK KNIGHT (loses an arm) – ' Tis but a scratch. BLACK KNIGHT (loses another arm)--It ' s just a flesh wound. BLACK KNIGHT (loses a leg)--I ' m invincible! BLACK KNIGHT (loses another leg)--all right, we'll call it a draw.

  

  

Python Dynamic properties and features (ii)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.