Object-oriented programming languages are often more convenient and safer to use than process-oriented languages when writing large programs. One of the reasons is: class mechanics.
Classes classify and encapsulate numerous data, making a data object a complete individual, close to real life, and highly abstract. However, Python's encapsulation of classes is not good, because all attributes and methods are public and you can access or write at will. You can modify the attributes of the class outside the class, or even add attributes. This is indeed unsettling.
Let’s summarize the solutions after learning.
#1, use 2 underscore prefixes to hide properties or methods.
__xxx #!/usr/bin/python3 #-*- coding:utf-8 -*- class Student: def __init__(self,name,score): self.name = name self.__score = score #将score隐藏起来,使之仅在类内部可用。 def __show(self): #一个隐藏的方法,同样只在内部可用 print(self.name,self.__score)#使用被隐藏的属性__score def Show(self): self.__show() #注意被隐藏方法的调用方式。 def main(): he = Student('Bob',95) he.Show() #显示:Bob 95 #print(he.__score) #AttributeError: 'Student' object has no attribute '__score' #he.__show() #AttributeError: 'Student' object has no attribute '__show' #隐藏属性真的被隐藏了吗?其实仍然可使用,使用格式 obj._className__attributeName #但是仅仅作为了解,不建议使用隐藏属性。 print(he._Student__show()) #显示:Bob 95 print(he._Student__score) # 显示: 95 if __name__=="__main__": main()
The impact of double underscores on class attributes:
1. Make the attribute only used inside this class, and cannot be directly read or modified by external or subclasses.
2. The attributes of classes that use _ _ will be renamed during implementation. For example, __age in the class will eventually become _A__age (name reorganization). This advantage is: it is usually used when involving Use it in the inherited parent class. This avoids being overridden by subclass properties.
#2. Create manageable properties.
Sometimes we need to do additional checks on the writing of attributes, reject writing of illegal values, and cause exceptions.
#!/usr/bin/python3 #-*- coding:utf-8 -*- class Student: def __init__(self,name,score): self.name = name self.score = score @property #实现属性的读取方法,读取实例的score值时,就会调用这个函数 def score(self): return self.__score @score.setter #实现属性写入方法,写入实例的score属性时,调用这个函数 def score(self,newVal): if not isinstance(newVal,(int,float)): raise TypeError('score value must be a number') if newVal>100 or newVal<0: raise ValueError('score value must between 0 and 100') self.__score = newVal def main(): he = Student('Bob',95) he.score = 100 #重新写入 print(he.score) #读取 if __name__=="__main__": main()
We can find: self.__score is where the attribute value is actually stored, and self.score is a function (but it is used Like a property), it is a method for getting and writing property values.
The socre.setter decorated function will also be called during initialization, because the call to self.score appears under the __init__() function
Since self.__score is only used to reference the value of the attribute , can it be named by another name? Such as saveScore.... Of course it is possible, but it is "exposed". We don't want it to be available externally, so we should
add __ to hide it to prevent accidental modification.
Sometimes, if you are sure that a certain class will not involve inheritance, then you can rewrite the above double underline into a single underline. Although it will not achieve the hidden effect, on the one hand, this will not It will trigger the name mangling mechanism,
to avoid making a fuss. On the other hand, starting with an underscore can remind the user that this attribute should not be used directly. Then, it depends on self-awareness.
An instance object can add attributes externally at will.
#!/usr/bin/python3 #-*- coding:utf-8 -*- class Student: def __init__(self,name,score): self.name = name self.score = score def main(): he = Student('Bob',95) he.age = 19 print(he.age) if __name__=="__main__": main() 使用__slots__ #!/usr/bin/python3 #-*- coding:utf-8 -*- class Student: __slots__ = ('name','score') #将属性名以字符串形式加入元组 def __init__(self,name,score): self.name = name self.score = score def main(): he = Student('Bob',95) he.age = 19 #AttributeError: 'Student' object has no attribute 'age' print(he.age) if __name__=="__main__": main()
In this way, the properties of the object are limited to the interior of the class.
But __slots__ cannot be inherited. Moreover, the original design intention of __slots__ is not the above usage, but to optimize the memory usage when creating a large number (tens of thousands) of objects.
Summary:
As I write, I find that the above techniques are of little significance. The designer of the class is the programmer himself, and so is the user. Therefore, the
reading and writing of the object attributes should be controlled by himself. The class design itself does not require too much protection code, otherwise it will be bloated and Efficiency is reduced. Protection measures should occur outside the class, so that the data received by the class object is always legal, which will be more lightweight and flexible. This is how I feel.
The above article briefly discussing the read and write permissions of Python object data is all the content shared by the editor. I hope it can give you a reference, and I also hope that everyone will support the PHP Chinese website.
For more articles on the read and write permissions of Python object data, please pay attention to the PHP Chinese website!