Uncover the reasons why Python allows setting non-existent class attributes without raising exceptions. Learn about instance dictionaries and how to restrict attribute assignment using slots.
---
This video is based on the question https://stackoverflow.com/q/63855914/ asked by the user 'fooiey' ( https://stackoverflow.com/u/13877993/ ) and on the answer https://stackoverflow.com/a/63855988/ provided by the user 'ShadowRanger' ( https://stackoverflow.com/u/364696/ ) at 'Stack Overflow' website. Thanks to these great users and Stackexchange community for their contributions.
Visit these links for original content and any more details, such as alternate solutions, latest updates/developments on topic, comments, revision history etc. For example, the original title of the Question was: Why doesn't python throw an exception when you set an attribute of a class that doesn't exist
Also, Content (except music) licensed under CC BY-SA https://meta.stackexchange.com/help/l...
The original Question post is licensed under the 'CC BY-SA 4.0' ( https://creativecommons.org/licenses/... ) license, and the original Answer post is licensed under the 'CC BY-SA 4.0' ( https://creativecommons.org/licenses/... ) license.
If anything seems off to you, please feel free to write me at vlogize [AT] gmail [DOT] com.
---
Understanding Python's Attribute Assignment: Why No Exception When Setting Non-Existent Attributes?
If you've ever encountered a situation in Python where you set an attribute on a class instance that doesn't exist beforehand, you might have been surprised to find that no exception was raised. This can lead to confusion, especially if you're trying to debug your code. Let's explore this behavior and understand the underlying mechanism as well as how you can control it.
The Problem
Consider the following code snippet:
[[See Video to Reveal this Text or Code Snippet]]
In this example, x is an instance of the Test class. Even though b has not been defined in the class, assigning a value to x.b does not throw an error. Instead, it successfully prints the values of both a and b. However, if you create another instance:
[[See Video to Reveal this Text or Code Snippet]]
You will encounter an AttributeError, which makes everything even more perplexing.
Understanding the Behavior
Inner Workings of Python Classes
In Python, instances of classes use a built-in dictionary, known as _dict__, to store their instance attributes. This means that Python does not differentiate between setting an attribute inside the __init_ method versus anywhere else. Here’s what happens:
Dynamic Attributes: When you assign a value to a new attribute (like b), Python dynamically creates this attribute in the instance's __dict__. There are no restrictions enforced on what attributes can exist.
Instance-wide Scope: The _init_ method initializes the state of an instance, but outside this method, you can add (or change) attributes freely.
Convenience vs. Restriction: This flexibility allows for convenience in certain coding scenarios, like computing attributes only when needed. If a method requires an attribute that is not yet assigned, it can catch the AttributeError and calculate it on the fly.
Flexibility in Python
This behavior of allowing arbitrary attribute assignment is common in scripting languages such as Perl, Ruby, and JavaScript. The design philosophy typically emphasizes flexibility over strictness. This allows developers to work with dynamic data structures and simplify code without excessive boilerplate.
Preventing Arbitrary Attribute Creation
If you find this flexibility more of a hindrance than a help, there are ways to enforce stricter control over attribute assignment.
Using _slots_
By defining _slots_ in your class, you can restrict what attributes can be created. Here’s how you can implement it:
[[See Video to Reveal this Text or Code Snippet]]
Benefits of Using __slots__:
Memory Efficiency: Instead of utilizing a dict for storing attributes, it uses a fixed-size array, which reduces memory usage.
Preventing New Attributes: If you try to assign to an attribute that is not listed in __slots__, Python will raise an AttributeError.
For example, after using __slots__, assigning to b would raise:
[[See Video to Reveal this Text or Code Snippet]]
Important Note
Keep in mind that using _slots_ disables weak references for instances of your classes. If you need weak references, you must include _weakref_ in the list of slots.
Conclusion
Understanding how Python handles attribute assignment can save you time and frustration in debugging. The flexibility afforded by dynamic attribute assignment can be both an asset and a source of confusion. By using __slots__, you can tighten control over your classes and ensure that only specified attributes can be created, leading to cleaner and more predictable code.
In Python, knowledge is power—understanding these intricacies will help you
Информация по комментариям в разработке