Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This exact question was <a href="https://mail.python.org/pipermail/python-list/2012-January/618570.html" rel="nofollow noreferrer">raised on Python-list</a> earlier this year. I'm just going to quote <a href="https://mail.python.org/pipermail/python-list/2012-January/618572.html" rel="nofollow noreferrer">Ian G. Kelly's response</a>:</p> <blockquote> <p>The behavior is by design. First, keeping object behavior in the class definition simplifies the implementation and also makes instance checks more meaningful. To borrow your Register example, if the "M" descriptor is defined by some instances rather than by the class, then knowing that the object "reg" is an instance of Register does not tell me anything about whether "reg.M" is a valid attribute or an error. As a result, I'll need to guard virtually every access of "reg.M" with a try-except construct just in case "reg" is the wrong kind of register.</p> <p>Second, the separation of class from instance also helps you keep object behavior separate from object data. Consider the following class:</p> <pre><code>class ObjectHolder(object): def __init__(self, obj): self.obj = obj </code></pre> <p>Don't worry about what this class might be useful for. Just know that it's meant to hold and provide unrestricted access to arbitrary Python objects:</p> <pre><code>&gt;&gt;&gt; holder = ObjectHolder(42) &gt;&gt;&gt; print(holder.obj) 42 &gt;&gt;&gt; holder.obj = range(5) &gt;&gt;&gt; print(holder.obj) [0, 1, 2, 3, 4] </code></pre> <p>Since the class is meant to hold arbitrary objects, it's even valid that somebody might want to store a descriptor object there:</p> <pre><code>&gt;&gt;&gt; holder.obj = property(lambda x: x.foo) &gt;&gt;&gt; print(holder.obj) &lt;property object at 0x02415AE0&gt; </code></pre> <p>Now suppose that Python invoked the descriptor protocol for descriptors stored in instance attributes:</p> <pre><code>&gt;&gt;&gt; holder = ObjectHolder(None) &gt;&gt;&gt; holder.obj = property(lambda x: x.foo) &gt;&gt;&gt; print(holder.obj) Traceback (most recent call last): File "&lt;stdin&gt;", line 1, in &lt;module&gt; AttributeError: 'ObjectHolder' object has no attribute 'foo' </code></pre> <p>In this case, the ObjectHolder would fail to simply hold the property object as data. The mere act of assigning the property object, a descriptor, to an instance attribute would <em>change the behavior</em> of the ObjectHolder. Instead of treating "holder.obj" as a simple data attribute, it would start invoking the descriptor protocol on accesses to "holder.obj" and ultimately redirect them to the non-existent and meaningless "holder.foo" attribute, which is certainly not what the author of the class intended.</p> </blockquote> <p>If you want to be able to support multiple instances of a descriptor, just make that descriptor's constructor take a name argument (prefix), and prefix the added attributes with that name. You could even create a namespace object (dictionary) within the class instance to hold all of the new property instances.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload