This has to do with class variables and instances variables.
Given the following:
<code>
class _class:
var = 0
#rest of the class
instance_b = _class()
_class.var=5
print instance_b.var # -> 5
print _class.var # -> 5
</code>
Initially this seems to make sense, note the difference between to last
two lines, one is refering to the class variable 'var' via the class
while the other refers to it via an instance.
However if one attempts the following:
<code>
instance_b.var = 1000 # -> _class.var = 5
_class.var = 9999 # -> _class.var = 9999
</code>
An obvious error occurs. When attempting to assign the class variable
via the instance it instead creates a new entry in that instance's
__dict__ and gives it the value. While this is allowed because of
pythons ability to dynamically add attributes to a instance however it
seems incorrect to have different behavior for different operations.
There are two possible fixes, either by prohibiting instance variables
with the same name as class variables, which would allow any reference
to an instance of the class assign/read the value of the variable. Or
to only allow class variables to be accessed via the class name itself.
Many thanks to elpargo and coke. elpargo assisted in fleshing out the
best way to present this.
perhaps this was intended, i was just wondering if anyone else had
noticed it, and if so what form would you consider to be 'proper'
either referring to class variables via the class itself or via
instances of that class. Any response would be greatly appreciated.
Graham
Nov 3 '05
166 8680
Antoon Pardon wrote: There is no instance variable at that point. How can it add 2, to something that doesn't exist at the moment.
Because 'a += 1' is only a shorthand for 'a = a + 1' if a is an
immutable object? Anyway, the behaviour is well documented. http://docs.python.org/ref/augassign.html says:
An augmented assignment expression like x += 1 can be rewritten as x = x
+ 1 to achieve a similar, but not exactly equal effect. In the augmented
version, x is only evaluated once. Also, when possible, the actual
operation is performed in-place, meaning that rather than creating a new
object and assigning that to the target, the old object is modified instead.
....
For targets which are attribute references, the initial value is
retrieved with a getattr() and the result is assigned with a setattr().
Notice that the two methods do not necessarily refer to the same
variable. When getattr() refers to a class variable, setattr() still
writes to an instance variable. For example:
class A:
x = 3 # class variable
a = A()
a.x += 1 # writes a.x as 4 leaving A.x as 3
Op 2005-11-03, Stefan Arentz schreef <st***********@ gmail.com>: Antoon Pardon <ap*****@forel. vub.ac.be> writes:
...
Fine, we have the code:
b.a += 2
We found the class variable, because there is no instance variable, then why is the class variable not incremented by two now? Because it really is executed as:
b.a = b.a + 2
That is an explanation, not a reason.
1. get 't'b.a and store it in a temporary 't' (found the instance) 2. add 2 to 't' 3. store 't' in 'b.a'
The last operation stores it into an instance variable.
[ I think you mean '(found the class variable)' in line 1 ]
All you are doing here is explain how the current implemantation treats
this. You are not giving arguments for why the result of this
implementation should be considered sane behaviour. > Remember, Python is a dynamic language.
So? Python being a dynamic language doesn't prevent the following to fail:
>>> a=1 >>> def f(): ... a += 2 ... >>> f() Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 2, in f UnboundLocalErr or: local variable 'a' referenced before assignment
See the 'global' keyword.
You missed the point. If python being a dynamic language would be the
answer to the interaction between instance and class variable, why
then is the interaction between local and global variable different,
why wouldn't the f code be executed as follows
1. get a and store in in a temporary 't' (found the global)
2. add 2 to 't'
3. store 't' in 'a'
The last operation storing it in f's local namespace.
--
Antoon Pardon
Antoon Pardon <ap*****@forel. vub.ac.be> writes: Op 2005-11-03, Stefan Arentz schreef <st***********@ gmail.com>: Antoon Pardon <ap*****@forel. vub.ac.be> writes:
...
Fine, we have the code:
b.a += 2
We found the class variable, because there is no instance variable, then why is the class variable not incremented by two now?
Because it really is executed as:
b.a = b.a + 2
That is an explanation, not a reason.
I'm just following the 1. get 't'b.a and store it in a temporary 't' (found the instance) 2. add 2 to 't' 3. store 't' in 'b.a'
The last operation stores it into an instance variable.
[ I think you mean '(found the class variable)' in line 1 ]
All you are doing here is explain how the current implemantation treats this. You are not giving arguments for why the result of this implementation should be considered sane behaviour.
Ah yes. Well, good luck with that. You seem to have decided that it is not
sane and who am I to argue with that. It depends on your state of mind :-)
The model makes sense in my opinion. If you don't like it then there are
plenty of other languages to choose from that have decided to implement
things differently.
Have fun, take care!
S.
On Thu, 03 Nov 2005 13:01:40 +0000, Antoon Pardon wrote: Seems perfectly sane to me.
What would you expect to get if you wrote b.a = b.a + 2? I would expect a result consistent with the fact that both times b.a would refer to the same object.
class RedList(list):
colour = "red"
L = RedList(())
What behaviour would you expect from len(L), given that L doesn't have a
__len__ attribute? Why do you expect b.a += 2 to give a different result?
I didn't know I did.
It seems to me that you do.
You didn't appear to be objecting to a line like x = b.a assigning the
value of 1 to x (although perhaps you do). If that was the case, then it
is perfectly reasonable to expect b.a = x + 2 to store 3 into b.a, while
leaving b.__class__.a untouched.
Of course, if you object to inheritance, then you will object to x = b.a
as well. Since ints are immutable objects, you shouldn't expect the value of b.a to be modified in place, and so there is an assignment to b.a, not A.a.
You are now talking implementation details. I don't care about whatever explanation you give in terms of implementation details. I don't think it is sane that in a language multiple occurence of something like b.a in the same line can refer to different objects
That's an implementation detail only in the sense that "while condition"
is a loop is an implementation detail. It is a *design* detail.
b is a name, and any reference to b (in the same namespace) will refer
to the same object. At least until you rebind it to another object.
But b.a is not a name, it is an attribute lookup, and by Python's rules of
inheritance that lookup will look up attributes in the instance, the
class, and finally any superclasses.
If you persist in thinking of b.a as a name referring to a single object,
of course you will be confused by the behaviour. But that's not what
attribute lookup does.
On the right hand side of an assignment, it will return the first existing
of b.__dict__['a'] or b.__class__.__d ict__['a']. On the left hand of an
assignment, it will store into b.__dict__['a'].
I think it even less sane, if the same occurce of b.a refers to two different objects, like in b.a += 2
Then it seems to me you have some serious design problems. Which would you
prefer to happen?
# Scenario 1
# imaginary pseudo-Python code with no inheritance:
class Paragraph:
ls = '\n' # line separator
para = Paragraph()
para.ls
=> AttributeError - instance has no attribute 'ls'
# Scenario 2
# imaginary pseudo-Python code with special inheritance:
class Paragraph:
ls = '\n' # line separator
linux_para = Paragraph()
windows_para = Paragraph()
windows_para.ls = '\n\r' # magically assigns to the class attribute
linux_para.ls
=> prints '\n\r'
# Scenario 3
# Python code with standard inheritance:
class Paragraph:
ls = '\n' # line separator
linux_para = Paragraph()
windows_para = Paragraph()
windows_para.ls = '\n\r'
linux_para.ls
=> prints '\n'
--
Steven.
On Thu, 03 Nov 2005 14:27:48 +0100, Sybren Stuvel wrote: Antoon Pardon enlightened us with: I would expect a result consistent with the fact that both times b.a would refer to the same object.
"b.a" is just a name, not a pointer to a spot in memory. Getting the value associated with that name is something different from assigning a new value to that name.
You've got the right concept, but not the right terminology. The "b"
before the dot is a name. The "a" after the dot is a name. But the whole
thing together is not a name: b.a is an attribute reference. You wouldn't
call b["a"] a name, and you shouldn't call b.a a name either.
--
Steven.
On Thu, 03 Nov 2005 13:35:35 +0000, Antoon Pardon wrote: Suppose I have code like this:
for i in xrange(1,11): b.a = b.a + i
Now the b.a on the right hand side refers to A.a the first time through the loop but not the next times. I don't think it is sane that which object is refered to depends on how many times you already went through the loop.
Well, then you must think this code is *completely* insane too:
py> x = 0
py> for i in range(1, 5):
.... x += i
.... print id(x)
....
140838200
140840184
140843160
140847128
Look at that: the object which is referred to depends on how many times
you've already been through the loop. How nuts is that?
I guess that brings us back to making ints mutable. I can't wait until I
can write 1 - 0 = 99 and still be correct!
--
Steven.
On Thu, 03 Nov 2005 14:13:13 +0000, Antoon Pardon wrote: Fine, we have the code:
b.a += 2
We found the class variable, because there is no instance variable, then why is the class variable not incremented by two now?
Because b.a += 2 expands to b.a = b.a + 2. Why would you want b.a =
<something> to correspond to b.__class__.a = <something>?
I'm not saying that it couldn't, if that was the model for inheritance you
decided to use. I'm asking why would you want it? What is your usage case
that demonstrates that your preferred inheritance model is useful?
--
Steven.
On Thu, 03 Nov 2005 15:13:52 +0100, Eric Nieuwland wrote: Stefan Arentz wrote: It is really simple. When you say b.a then the instance variable 'a' is looked up first. If it does not exist then a class variable lookup is done. This mixing of class and instance variable might be the cause of confusion...
I think of it as follows: 1 When the class statement ends a class object is created which is filled by all the statements inside the class statement This means all variables and functions (methods) are created according to the description. NOTE This happens just once.
Yes.
2 When an instance of the class is created, what effectively happens is that a shallow copy of the class object is made. Simple values and object references are copied.
No.
py> class Parrot:
.... var = 0
....
py> p = Parrot()
py> Parrot.var is p.var
True
py> Parrot.var = {"Hello world": [0, 1, 2]}
py> Parrot.var is p.var
True
It all boils down to inheritance. When Python does a look up of an
attribute, it looks for an instance attribute first (effectively trying
instance.__dict __['name']). If that fails, it looks up the class second
with instance.__clas s__.__dict__['name'], and if that fails it goes into a
more complex search path looking up any superclasses (if any).
This explains: - why methods and complex objects (e.g. lists) are shared among instances of a class and the class itself - simple values are not shared
No. it is all about the inheritance, and mutable/immutable objects.
--
Steven.
Steven D'Aprano wrote: On Thu, 03 Nov 2005 15:13:52 +0100, Eric Nieuwland wrote: 2 When an instance of the class is created, what effectively happens is that a shallow copy of the class object is made. Simple values and object references are copied.
No.
py> class Parrot: ... var = 0 ... py> p = Parrot() py> Parrot.var is p.var True py> Parrot.var = {"Hello world": [0, 1, 2]} py> Parrot.var is p.var True
It all boils down to inheritance. When Python does a look up of an attribute, it looks for an instance attribute first (effectively trying instance.__dict __['name']). If that fails, it looks up the class second with instance.__clas s__.__dict__['name'], and if that fails it goes into a more complex search path looking up any superclasses (if any).
Note my use of "effectivel y" and "shallow copy". Your example
demonstrates how Python postpones the shallow copy until you tell the
object to differ from the class/
The examples used only use a class an an instance thereof. They are
valid without inheritance. This explains: - why methods and complex objects (e.g. lists) are shared among instances of a class and the class itself - simple values are not shared
No. it is all about the inheritance, and mutable/immutable objects.
NO. You're referring to the implemented mechanism. Other
implementations with the same semantics are possible.
In article <dk**********@w ake.carmen.se>,
Magnus Lycka <ly***@carmen.s e> wrote:
.... On the other hand:
>>> class C: ... a = [1] ... >>> b=C() >>> b.a += [2] >>> b.a [1, 2] >>> C.a
[1, 2]
I can understand that Guido was a bit reluctant to introduce += etc into Python, and it's important to understand that they typically behave differently for immutable and mutable objects.
As far as I know, Guido has never added a feature reluctantly.
He can take full responsibility for this misguided wart.
Donn Cave, do**@u.washingt on.edu This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: A |
last post by:
Hi,
I have always been taught to use an inialization list for initialising data
members of a class. I realize that initialsizing primitives and pointers use
an inialization list is exactly the same as an assignment, but for class
types it has a different effect - it calls the copy constructor.
My question is when to not use an initalisation list for initialising data
members of a class?
|
by: xuatla |
last post by:
Hi,
I encountered the following compile error of c++ and hope to get your help.
test2.cpp: In member function `CTest CTest::operator+=(CTest&)':
test2.cpp:79: error: no match for 'operator=' in '*this =
CTest::operator+(CTest&)((+t2))'
test2.cpp:49: error: candidates are: CTest CTest::operator=(CTest&)
make: *** Error 1
|
by: Chris |
last post by:
Hi,
I don't get the difference between a struct and a class !
ok, I know that a struct is a value type, the other a reference type, I
understand the technical differences between both, but conceptually speaking
: when do I define something as 'struct' and when as 'class' ?
for example : if I want to represent a 'Time' thing, containing :
- data members : hours, mins, secs
|
by: NevilleDNZ |
last post by:
Can anyone explain why "begin B: 123" prints, but 456 doesn't?
$ /usr/bin/python2.3 x1x2.py
begin A:
Pre B: 123 456
begin B: 123
Traceback (most recent call last):
File "x1x2.py", line 13, in ?
A()
File "x1x2.py", line 11, in A
|
by: lovecreatesbea... |
last post by:
Could you tell me how many class members the C++ language synthesizes
for a class type? Which members in a class aren't derived from parent
classes?
I have read the book The C++ Programming Language, but there isn't a
detail and complete description on all the class members, aren't they
important to class composing? Could you explain the special class
behavior in detail? Thank you very much.
| |
by: tshad |
last post by:
Using VS 2003, I am trying to take a class that I created to create new
variable types to handle nulls and track changes to standard variable types.
This is for use with database variables. This tells me if a variable has
changed, give me the original and current value, and whether the current
value and original value is/was null or not.
This one works fine but is recreating the same methods over and over for
each variable type.
...
|
by: d.s. |
last post by:
I've got an app with two classes, and one class (InventoryInfoClass)
is an object within the other class (InventoryItem). I'm running into
problems with trying to access (get/set) a private variable within the
included class (InventoryInfo) from the "including" class
(InventoryItem).
Here's the code, trimmed down. I've included ********* at the start
of the first line that's blowing up on me. I'm sure others that try
to access the...
|
by: John Doe |
last post by:
Hi,
I wrote a small class to enumerate available networks on a smartphone :
class CNetwork
{
public:
CNetwork() {};
CNetwork(CString& netName, GUID netguid):
_netname(netName), _netguid(netguid) {}
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look !
Part I. Meaning of...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth.
The Art of Business Website Design
Your website is...
| |
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own....
Now, this would greatly impact the work of software developers. The idea...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules.
He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms.
Adolph will...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one.
At the time of converting from word file to html my equations which are in the word document file was convert into image.
Globals.ThisAddIn.Application.ActiveDocument.Select();...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...
| |