Python magic method-detailed description of attribute access control and python Access Control

Source: Internet
Author: User

Python magic method-detailed description of attribute access control and python Access Control

Attribute Access Control

The so-called attribute access control is to control the behavior of the Point Number access attribute. It is not only the exterior of the class, but also the internal control of the class. For details about the code, see the real chapter and explain the Code:

• _ Getattr _ (self, item)

Define when accessingDoes not existThe behavior of the attribute. Note that the attribute does not exist.

Class Foo (object): def _ init _ (self, value): self. value = value def _ getattr _ (self, item): print item # view the obtained print type (item) # return 'attr: % s' % item # The Last Thing returned to see how its behavior works. a = Foo ('scolia ') # create an instance.

Test:

print a.valueprint type(a.value)

Its behavior is normal before it is defined. Let's see what happens when accessing a non-existent attribute:

print a.abc

Normally, an exception is thrown when accessing a non-existent attribute, but three rows are output here. The first two rows are output by the method, and the last row is output by the external print statement, the return Value of the method is output. The method returns the name of the accessed attribute in the form of a string.

After knowing the above information, we can customize more:

Class Foo (object): def _ init _ (self, value): self. value = value def _ getattr _ (self, item): if item = 'scolia ': return 'can not set attr: % s' % item # When you access a nonexistent scolia attribute, print a sentence without error else: raise AttributeError ('not attr name: % s' % item) # An exception is triggered when accessing other non-existent attributes.

Test:

A = Foo (123) print a. value # access existing attributes

Print a. scolia # The access does not exist, but we do some special processing.

No exception is triggered, as we imagined.

Print a. good # access to a non-existent attribute should trigger an exception

This triggers the exception we want.

This method must be called only when an attribute does not exist. For example:

a.scolia = 321print a.scolia

This propertyAlready existsSo this method is not called when you access it, and any processing in the method is not effective.

More advanced skills:

Class Foo (object): def _ init _ (self, value, defulat = None): self. value = value self. _ defulat = defulat def _ getattr _ (self, item): item = item. lower () # Use the string method to lower case if item in self. _ dict __: return self. _ dict _ [item] # else: self. _ dict _ [item] = self. _ defulat # If the property does not exist, add the property and use the default value return self. _ dict _ [item] a = Foo (123). scolia = 321 print. SCOliaprint. good

We implement case-insensitive access to attributes and automatically add non-existent attributes.

The secret here is to use the _ dict _ attribute. I have discussed this attribute in the class attributes. This attribute is automatically created by python. It is a dictionary that contains all the attributes of an object. The keys in the dictionary are the attribute names, and the corresponding values are the attribute values. Therefore, adding keys and values to this dictionary is equivalent to adding attributes and attribute values to the object.

• _ Setattr _ (self, key, value)

Defines the behavior when setting properties, including the setting behavior in the _ init _ initialization function:

class Foo(object):  def __init__(self, value, defulat=None):    self.value = value  def __setattr__(self, key, value):    print key, type(key)    print value, type(value)a = Foo('scolia')b = Foo(123)

Here, we can see that the attribute addition behavior in the initialization function is also under control. The key obtains the attribute name in the form of a string, and the value obtains the attribute value, the attribute values vary according to the input values.

Here, we only printed a few words without adding attributes. So when we try to access the corresponding attributes, we will find that there is no at all:

print a.value

An exception is triggered, indicating that no corresponding attribute exists.

After knowing this, we can do a lot of things, such as converting all attribute names into lower-case or upper-case names, and controlling that some attribute names cannot be added. However, here you cannot use self. key = value to add attributes, because key is always a string. In this case, the _ dict _ attribute is used. You can add the corresponding key-value pair to the dictionary.

• _ Delattr _ (self, item)

Defines the behavior of deleting an attribute. item also obtains a string-type attribute name. The details are unordered, you only need to drop the _ dict _ dictionary, which corresponds to the key and value. In addition, this method is also called to delete nonexistent attributes.

• _ Getattribute _ (self, name)

This method defines the access behavior of all attributes. Note that it is all, rather than the nonexistent content in _ getattr. After this method is implemented, the _ getattr _ method will be overwritten. After all, all covered methods do not exist.

This method is only valid in the new class.

However, you can also explicitly call _ getattr __, such as. _ getattr _ is used to use this masked method, or it is automatically called when AttributeError is triggered.

However, this method is not recommended because many unpredictable exceptions may occur. The most common is endless recursive calls, for example:

class Foo(object):  def __init__(self, value):    self.value = value  def __getattribute__(self, item):    return self.__dict__[item]a = Foo('scolia')print a.value

This code looks normal, but there is a trap here, because all attribute access in the class is controlled by these magic methods, including the several magic methods described above. They seem to have higher permissions than normal magic methods.

But this leads to a problem, such as self. _ dict _ [item] is also controlled by attribute access, although this attribute is created by python for us.

That is to say, when obtaining self. _ dict _, the _ getattribute _ method is called again, And self. _ dict _ is called in the method __. In this way, the infinite loop will eventually throw an exception.

The exception information is very long. Here I pull the screenshot to the end.

In fact, not only does this magic method cause such an exception, but the above several magic methods may have this problem, but this magic method has a higher permission, so exceptions are more likely to occur.

This is why this magic method is not recommended. Be careful when using other property control methods.

So far, we have learned that there are only two methods to access the attribute. One is to access the attribute directly with the DoT number, and the other is to access the _ dict _ attribute through the DoT number first, then obtain the corresponding key-value pairs in the dictionary. Both methods are controlled by _ getattribute _. Calling them is equivalent to self-calling without an end point (self-calling with an end point can sometimes improve efficiency ), how can this method be used?

The trick is to call this method of the parent class:

Class Foo (object): def _ init _ (self, value): self. value = value def _ getattribute _ (self, item): return object. _ getattribute _ (self, item) # The non-binding method must explicitly pass selfa = Foo ('scolia ') print. value

The object method is called here, if it involves inheritance:

Class Boo (Foo): def _ init _ (self, value): self. value = value def _ getattribute _ (self, item): return Foo. _ getattribute _ (self, item) # return super (Boo, self ). _ getattribute _ (item) can also use the super function to enable python to automatically search for this method in its parent class. A = Foo ('scolia ') print a. valueb = Boo (123) print B. value

Access is normal.

In fact, the final call is still an object or other built-in type method.

However, we cannot determine how the object is implemented, because it may be written in C, and can be used as long as it is used, although this method is not used much.

A complete example is attached:

Class Foo (object): def _ init _ (self, value): self. value = value def _ getattr _ (self, item): if item = 'scolia ': return 'no attr: % s' % item elif item in self. _ dict __: return self. _ dict _ [item] else: raise AttributeError ('no attr: % s' % item) def _ setattr _ (self, key, value ): if key = 'good ': print 'can not set the attr: good' else: self. _ dict _ [key] = value def _ delattr _ (self, item): if item = 'A': print 'no attr: good 'else: del self. _ dict _ [item] def _ getattribute _ (self, item): if item = 'A': raise AttributeError ('not A') return object. _ getattribute _ (self, item) a = Foo ('scolia ') print. value # normal access. a = 123 # _ getattribute _ will trigger the AttributeError exception. At this time, the AttributeError is called _ getattr _ # and _ getattr _ adds this attribute, so the final exception is not triggered, print. a # The results can access del. a # Try to delete this attribute print. a # deletion is blocked, so this attribute is still in. good = 'good' # print. good # Access failed

Result:

The above python magic method-detailed explanation of attribute access control is all the content that I have shared with you. I hope to give you a reference and support for the help house.

Related Article

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.