Python descriptors with old-style classes

2024/9/16 23:25:51

I tried to google something about it. Why do non-data descriptors work with old-style classes?

Docs say that they should not:
"Note that descriptors are only invoked for new style objects or classes (ones that subclass object() or type()).".

class Descriptor(object):def __init__(self):self.x = 1def __get__(self, obj, cls=None):return self.xclass A:x = Descriptor()a = A()
a.x>>> 1

Thanks.

Answer

You are right to question the documentation. I've tried looking through CPython sources to find an explanation, but be warned: I'm no expert.

From my understanding, attribute lookup and descriptor __get__ invocation occurs in instance_getattr2 (chosen extracts):

v = class_lookup(inst->in_class, name, &klass);
if (v != NULL) {f = TP_DESCR_GET(v->ob_type);if (f != NULL) {PyObject *w = f(v, (PyObject *)inst, (PyObject *)(inst->in_class));}
}

So either I am missing something, or nothing in the implementation requires a new-style object (which contradicts the documentation).

For the record, I tried recompiling Python to restrict descriptor invocation to new style classes objects, but it actually brought up a gigantic mess. I learned in the process that class methods themselves are implemented as descriptors: this is the mechanism used to return bound or unbound method objects depending on the usage. For example:

>>> class A:
...     def foo():
...         pass
...
>>> A.foo.__get__(None, A)
<unbound method A.foo>
>>> A.foo.__get__(A(), A)
<bound method A.foo of <__main__.A instance at 0x000000000229CC48>>

As a result, it seems that preventing descriptor invocation for attributes of old-style objects or classes would also prevent method calls on them, at least with CPython implementation.

Once again, I'm no expert and this is the first time I dive into Python implementation, so I could very well be wrong. I've filed an issue to try to clarify this.

https://en.xdnf.cn/q/72873.html

Related Q&A

Decrypting a file to a stream and reading the stream into pandas (hdf or stata)

Overview of what Im trying to do. I have encrypted versions of files that I need to read into pandas. For a couple of reasons it is much better to decrypt into a stream rather than a file, so thats m…

How to replace accents in a column of a pandas dataframe

I have a dataframe dataSwiss which contains the information Swiss municipalities. I want to replace the letter with accents with normal letter.This is what I am doing:dataSwiss[Municipality] = dataSwis…

Comparison of multi-threading models in Julia =1.3 and Python 3.x

I would like to understand, from the user point of view, the differences in multithreading programming models between Julia >= 1.3 and Python 3.Is there one that is more efficient than the other (in…

How to do multihop ssh with fabric

I have a nat and it has various server So from my local server I want to go to nat and then from nat i have to ssh to other machinesLocalNAT(abcuser@publicIP with key 1)server1(xyzuser@localIP with key…

Python - Converting CSV to Objects - Code Design

I have a small script were using to read in a CSV file containing employees, and perform some basic manipulations on that data.We read in the data (import_gd_dump), and create an Employees object, cont…

Python multithreading - memory not released when ran using While statement

I built a scraper (worker) launched XX times through multithreading (via Jupyter Notebook, python 2.7, anaconda). Script is of the following format, as described on python.org:def worker():while True:i…

Delete files that are older than 7 days

I have seen some posts to delete all the files (not folders) in a specific folder, but I simply dont understand them.I need to use a UNC path and delete all the files that are older than 7 days.Mypath …

Doctests: How to suppress/ignore output?

The doctest of the following (nonsense) Python module fails:""" >>> L = [] >>> if True: ... append_to(L) # XXX >>> L [1] """def append_to(L):…

Matplotlib not showing xlabel in top two subplots

I have a function that Ive written to show a few graphs here:def plot_price_series(df, ts1, ts2):# price series line graphfig = plt.figure()ax1 = fig.add_subplot(221)ax1.plot(df.index, df[ts1], label=t…

SQLAlchemy NOT exists on subselect?

Im trying to replicate this raw sql into proper sqlalchemy implementation but after a lot of tries I cant find a proper way to do it:SELECT * FROM images i WHERE NOT EXISTS (SELECT image_idFROM events …