Comments (8)
@dec1 Can you show me an example in code that matches your expectations? The result of __getattr__
is cached in the __dict__
of the object, whereas __getattribute__
is never cached. See this part of the documentation. Please reopen if you have a more clear example. Thanks!
from effectivepython.
class MyClass(object):
def __init__(self):
self.exists = 5
def __getattr__(self, name):
print('Called __getattr__(%s)' % name)
value = 'Value for %s' % name
#setattr(self, name, value)
return value
data = MyClass()
for i in range(1,5):
print("(", i, ")")
data.foo
( 1 )
Called __getattr__(foo)
( 2 )
Called __getattr__(foo)
( 3 )
Called __getattr__(foo)
( 4 )
Called __getattr__(foo)
__getattr__
gets called every time that data.foo
is accessed
from effectivepython.
tested with python 3.6.1
from effectivepython.
Thanks for the working example, that makes it more clear where the confusion is.
The text from Item 32 is:
Understand that
__getattr__
only gets called once when accessing a missing attribute, whereas__getattribute__
gets called every time an attribute is accessed.
The key word here is missing. In your example, you even have the line # setattr(self, name, value)
that demonstrates the difference. Once you setattr
for the attribute name, then __getattr__
will not get called again.
Here's a modification to your example that shows the difference:
class MyClass(object):
def __init__(self):
self.exists = 5
def __getattr__(self, name):
print('Called __getattr__(%s)' % name)
value = 'Value for %s' % name
setattr(self, name, value)
return value
def __getattribute__(self, name):
print('Called __getattribute__(%s)' % name)
return object.__getattribute__(self, name)
data = MyClass()
for i in range(1, 5):
print("(%d)" % i)
data.foo
Output:
(1)
Called __getattribute__(foo)
Called __getattr__(foo)
(2)
Called __getattribute__(foo)
(3)
Called __getattribute__(foo)
(4)
Called __getattribute__(foo)
from effectivepython.
The statement
... getattr only gets called once when accessing a missing attribute, ....
is clearly wrong or at least very misleading.
A correct (general) statement would be
.. getattr only gets called when (every time) a missing attribute is accessed, ....
In the special case where you create the attribute after the first access (eg in the function __getattr__
itself) then __getattr__
will not be called again, because it's then no longer missing.
You could just as well create the attribute the second time __getattr__
gets called and say
... getattr only gets called twice when accessing a missing attribute, ....
This would be equally wrong/misleading.
from effectivepython.
I see your point there. The "special case" is the most common case I've seen. But I agree that I'm assuming something implicitly about the way __getattr__
is used in practice (where its definition usually calls setattr
).
I think it would be more clear to update the suggestion text to this:
Understand that getattr only gets called when accessing a missing attribute, whereas getattribute gets called every time any attribute is accessed.
from effectivepython.
Yes, this would be a good and sufficient change.
Best Wishes, Declan
from effectivepython.
This will be resolved in a future release. Thanks
from effectivepython.
Related Issues (20)
- Item 45 Flawed code when delta is less than zero HOT 1
- Item 11: The result of slicing a list is a whole new list... HOT 2
- syntax highlighting missing - page 5 HOT 1
- Item #9: Incorrect indentation for return statement in coprime_alternate function HOT 1
- Item 63: "WriteThread" class implementation HOT 2
- Item 51: decorator isn't applied to `dict.__setitem__` method HOT 2
- bytes.encode/str.decode -> str.encode/bytes.decode? HOT 1
- item_57.py HOT 2
- Item 5: Code example missing indent HOT 2
- Item 3: (page 10, first line) Use of bytes and str types should be the other way round HOT 1
- Item 78: page 373, wrong cross-reference: says “see Item 76”, should be “see Item 77” HOT 1
- Item 78: page 374, wrong function name: says `feed_func`, should be `feed_animal` HOT 2
- Item 35, pages 136 & 137: `while` loop does not break at 0, needs another `break` statement HOT 3
- Item 36, page 140: logical error in the definition of `dropwhile` HOT 1
- Item 47, pages 199 & 200: error in code snippet: `data` param value is never assigned to the protected `_data` attribute HOT 2
- Item 3, page 9, 2nd edition: "%s" invokes `__str__` if there's `__str__` else `__repr__` HOT 1
- Item 6: Functions need return statement HOT 2
- Item 51: Possible logic mistake, needs clarification HOT 1
- Item 37: unused variable in for loop HOT 1
- Please Delete. Issue resolved. HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from effectivepython.