Custom attribute access and dynamic attribute setting of Python classes

Keywords: Python Back-end

This article mainly introduces the methods of accessing some custom attributes of python classes and the dynamic attribute setting of classes, that is, python's built-in function setattr().

Custom attribute access

What are attributes? Are the following examples a and b attributes? No, they are global variables. An attribute is a member variable in a class. It can also be understood that an attribute is a class variable.

a = 11234
b = 'python'

Variables in a class are static variables that can be accessed directly by classes. python is a dynamic language. Any instance object can dynamically add or delete attributes. A class defines a scope, and class instance objects also introduce a scope, which is different from the scope defined by a class. When searching for attributes in the class instance object, first search in the scope of the instance itself. If it is not found, then search in the scope of the class definition.

When assigning a value to a class instance attribute, it will actually add an attribute or modify an attribute in the scope defined by the class instance, but it will not affect the attribute with the same name defined in the corresponding class. So how does the process from accessing properties to returning results work? It is realized by the following magic methods.

Use of relevant methods

  • __ getattribute__: This method will be triggered first to find the attribute
  • __ getattr__: Triggered when the search attribute is not found
  • __ setattr__: Triggered when setting properties
  • __ delattr__: Triggered when a property is deleted

In order to intuitively feel what an instance does when accessing properties, let's take a look at the following example:

class TestCase:
    att_1 = 'hello'  # Define class properties
    att_2 = 'python'

    def test_func(self):  # Definition method
        print("This is a method")

    def __getattribute__(self, item):
        # Property access Interceptor: when an object accesses a property, it will automatically trigger this method, which will determine the returned property value
        # Application scenario: when accessing a nonexistent attribute, you don't want it to report an error. You can use try--except to catch an exception and return a value or prompt information
        # try:
        #     return super().__getattribute__(item)  # Call the parent class real__ getattribute__ Method returns the correct property value
        # except AttributeError:
        #     print(item, ': the property does not exist!')
        # If the try method is used, it will not be triggered__ getattr__ Method, because the exception when the property cannot be found has been caught here
        print("I am__getattribute__,I'm working")
        return super().__getattribute__(item)    # Call the method of the parent class to return the found result. If it is not called, it will not be returned

    def __getattr__(self, att_name):
        # When an object accesses a property, the property does not exist, an exception is thrown, and the property is deleted__ getattr__ Method capture
        # Then execute the code of this method, which is equivalent to catching exceptions
        print("I am__getattr__,I'm working")
        return att_name + "This is what I'm looking for, but I can't find it"

    def __setattr__(self, att_name, value):
        # This method is triggered when the property is set
        print("I am__setattr__,I'm working")
        super().__setattr__(att_name, value)    # Call the method of the parent class and set the property. If it is not called, it will not really set the property

    def __delattr__(self, att_name):
        print("I am__delattr__,I'm working")
        print("This is something I'm about to delete{}".format(att_name))
        super().__delattr__(att_name)   # Call the method of the parent class and delete the property. You can't delete it without calling it


res = TestCase()  # Instantiate object
print('-----------------Access properties----------------')
print(res.att_1)    # Access class properties. See the method passed when the res instance object accesses properties through the running results__ getattribute__

print('\n-----------------Access non-existent properties----------------')
print(res.att_3)

print('\n-----------------set a property----------------')
res.att_3 = 'new_attr'

print('\n-----------------Delete attribute----------------')
del res.att_3

Operation results:

-----------------Access properties----------------
I am__getattribute__,I'm working
hello

-----------------Access non-existent properties----------------
I am__getattribute__,I'm working
 I am__getattr__,I'm working
att_3 This is what I'm looking for, but I can't find it

-----------------set a property----------------
I am__setattr__,I'm working

-----------------Delete attribute----------------
I am__delattr__,I'm working
 This is something I'm about to delete att_3

From the results, we can see that when the instance accesses the property, it will be triggered automatically__ getattribute__ () method, and then this method determines the returned attribute value; When an instance accesses a property that does not exist, an exception is thrown, and this exception is ignored__ getattr__ () method capture, and then execute the code of the method, which is equivalent to the built-in exception capture; Similarly, when setting or deleting an attribute, the corresponding will be triggered automatically__ setattr__ () method or__ delattr__ () method.

However, it should be noted that when customizing these methods, you must remember to call the corresponding parent method and return the results. Otherwise, you just execute your customized things and don't really do what it needs to do.

Dynamic attribute settings

setattr() is a built-in function of python, which is used to dynamically set instance properties. Syntax: setattr(object, name, value)

  • Parameter 1: object object

  • Parameter 2: name - the name (string type) of the attribute to be set for the object

  • Parameter 3: value attribute value

'''
No one answers the problems encountered in learning? Xiaobian created a Python exchange of learning QQ Group: 725638078
 Look for like-minded friends to help each other,There are also good videos and tutorials in the group PDF e-book!
'''
class TestCase:
    """This is a class that stores test case data"""
    pass


cases = [
    {'case_id': 1, 'data': '123', 'actual': 'Fail', 'excepted': 'adopt'},
    {'case_id': 2, 'data': '123', 'actual': 'adopt', 'excepted': 'adopt'},
    {'case_id': 3, 'data': '123', 'actual': 'Fail', 'excepted': 'adopt'},
    {'case_id': 4, 'data': '123', 'actual': 'adopt', 'excepted': 'adopt'},
]

res = []  # Create a new empty list to store the results
for i in cases:
    case = TestCase()  # Create an instance object
    for k, v in i.items():
        # Set the key and value of the dictionary in each use case data as the attribute and value of the instance, such as case_id = 1,data = 123, etc. set all key value pairs of a dictionary as the attributes of an instance
        setattr(case, k, v)  
    res.append(case)    # Save the created object to the result

print(res)  # There are 4 objects stored
print("\n Read the first test case data by field:")
print("case_id:", res[0].case_id)   # Read the case of the first object_ ID attribute value
print("data:", res[0].data)
print("actual:", res[0].actual)
print("excepted:", res[0].excepted)

print("\n Read the complete data of the first test case:")
print(res[0].__dict__)

Operation results:

[<__main__.TestCase object at 0x0000019F15F573C8>, <__main__.TestCase object at 0x0000019F15F57C18>, <__main__.TestCase object at 0x0000019F16009C18>, <__main__.TestCase object at 0x0000019F16009C50>]

Read the first test case data by field:
case_id: 1
data: 123
actual: Fail
excepted: adopt

Read the complete data of the first test case:
{'case_id': 1, 'data': '123', 'actual': 'Fail', 'excepted': 'adopt'}

In the above running results, for example, < main.testcase object at 0x0000019f15f573c8 > this is an instance object of TestCase() class, which is its memory address. setattr() dynamically sets the attribute, which is equivalent to case.case_id=1 sets an attribute for the instance, but the example above circularly splits the data of the whole list into the attributes of four instances.

Similarly, there is also a getattr(object, name) built-in function in python, which is used to return the attribute of an instance. Two parameters are required, one is the object name and the other is the attribute name, which returns the attribute value of the attribute. There are no more examples here. Use it yourself!

In addition, the last one in the above example is used__ dict__ Object property, which is used to obtain all properties of the instance object and return them in the form of a dictionary.

At the end, I recommend a very good learning tutorial for you. I hope it will be helpful for you to learn Python!

Python basic introductory tutorial recommendation: more Python Video Tutorials - pay attention to station B: Python learners

Python crawler case tutorial recommendation: more Python Video Tutorials - follow site B: Python learners

Posted by alba on Fri, 12 Nov 2021 13:14:04 -0800