473,769 Members | 6,597 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Class Variable Access and Assignment

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 8669
Antoon Pardon <ap*****@forel. vub.ac.be> writes:
Op 2005-11-04, Mike Meyer schreef <mw*@mired.org> :
Antoon Pardon <ap*****@forel. vub.ac.be> writes:
Op 2005-11-03, Mike Meyer schreef <mw*@mired.org> :
Antoon Pardon <ap*****@forel. vub.ac.be> writes:
>> 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.
Except they *don't*. This happens in any language that resolves
references at run time.
Python doesn't resolve references at run time. If it did the following
should work.


You left out a key word: "all".
a = 1
def f():
a = a + 1

f()


If Python didn't resolve references at run time, the following
wouldn't work:
> def f():

... global a
... a = a + 1
...
> a = 1
> f()
>
Why do you think so? I see nothing here that couldn't work with
a reference resolved during compile time.


a - in the global name space - doedn't exist when f is compiled, and
hence can't be dereferenced at compile time. Of course, sufficiently
advanced analysis can figure out that a would exist before f is run,
but that's true no matter how a is added. That isn't the way python
works.
But letting that aside. There is still a difference between resolving
reference at run time and having the same reference resolved twice
with each resolution a different result.

The second is a direct result of the first. The environment can change
between the references, so they resolve to different results.

No the second is not a direct result of the first. Since there is
only one reference, I see nothing wrong with the environment
remebering the reference and reusing it if it needs the reference
a second time.


Please stay on topic: we're talking about "a = a + 1", not "a += 1".
The former has two references, not one. I've already agreed that the
semantics of += are a wart.

<mike
--
Mike Meyer <mw*@mired.or g> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 4 '05 #111
Steven D'Aprano <st***@REMOVETH IScyber.com.au> writes:
equal? Some things are a matter of objective fact: should CPython use a
byte-code compiler and virtual machine, or a 1970s style interpreter that
interprets the source code directly?


For the record, I've only seen one interpreter that actually
interpreted the source directly. Pretty much all of the rest of them
do a lexical analysis, turning keywords into magic tokens (dare I say
"byte codes") and removing as much white space as possible. Or maybe
that's what you meant?

<mike
--
Mike Meyer <mw*@mired.or g> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 4 '05 #112
Paul Rubin wrote:
Steven D'Aprano <st***@REMOVETH IScyber.com.au> writes:
Follow the logical implications of this proposed behaviour.

class Game:
current_level = 1
# by default, games start at level one

That's bogus. Initialize the current level in the __init__ method
where it belongs.


But there is a relevant use case for this:

If you have a class hierarchy, where the difference between the
classes is mainly/completely a matter of data, i.e. default
values. Then it's very convenient to use such defaults in the
class scope.

Of course, you *could* have an __init__ in the base class that
copies this data from class scope to instance scope on instance
creation, but why make it more complicated?

You could also imagine cases where you have many instances and
a big immutable variable which typically stays as default, but
must sometimes vary between instances.

As I explained in another post, member lookups in the instance
must look in the class to find methods, so why not get used to
the fact that it works like this, and use it when it's convenient.
It's not as if anyone puts a gun to your head and force you to
use this feature.
Nov 5 '05 #113
Steven D'Aprano <st***@REMOVETH IScyber.com.au> writes:
A basic usage case:

class Paper:
size = A4
def __init__(self, contents):
# it makes no sense to have class contents,
# so contents go straight into the instance
self.contents = contents


So add:

self.size = Paper.size

and you've removed the weirdness. What do you gain here by inheriting?
Nov 5 '05 #114
On Fri, 04 Nov 2005 02:59:35 +1100, Steven D'Aprano <st***@REMOVETH IScyber.com.au> wrote:
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 the class variable doesn't define a self-mutating __iadd__
(which is because it's an immutable int, of course). If you want
b.__dict__['a'] += 2 or b.__class__.__d ict__['a'] += 2 you can
always write it that way ;-)

(Of course, you can use a descriptor to define pretty much whatever semantics
you want, when it comes to attributes).

Because b.a += 2 expands to b.a = b.a + 2. Why would you want b.a =
No, it doesn't expand like that. (Although, BTW, a custom import could
make it so by transforming the AST before compiling it ;-)

Note BINARY_ADD is not INPLACE_ADD:
def foo(): # for easy disassembly ... b.a += 2
... b.a = b.a + 2
... import dis
dis.dis(foo)

2 0 LOAD_GLOBAL 0 (b)
3 DUP_TOP
4 LOAD_ATTR 1 (a)
7 LOAD_CONST 1 (2)
10 INPLACE_ADD
11 ROT_TWO
12 STORE_ATTR 1 (a)

3 15 LOAD_GLOBAL 0 (b)
18 LOAD_ATTR 1 (a)
21 LOAD_CONST 1 (2)
24 BINARY_ADD
25 LOAD_GLOBAL 0 (b)
28 STORE_ATTR 1 (a)
31 LOAD_CONST 0 (None)
34 RETURN_VALUE

And BINARY_ADD calls __add__ and INPLACE_ADD calls __iadd__ preferentially.

About __ixxx__:
"""
These methods are called to implement the augmented arithmetic operations
(+=, -=, *=, /=, %=, **=, <<=, >>=, &=, ^=, |=).
These methods should attempt to do the operation in-place (modifying self)
and return the result (which could be, but does not have to be, self).
If a specific method is not defined, the augmented operation falls back
to the normal methods. For instance, to evaluate the expression x+=y,
where x is an instance of a class that has an __iadd__() method,
x.__iadd__(y) is called. If x is an instance of a class that does not define
a __iadd() method, x.__add__(y) and y.__radd__(x) are considered, as with
the evaluation of x+y.
"""

<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?


It can be useful to find-and-rebind (in the namespace where found) rather
than use separate rules for finding (or not) and binding. The tricks for
boxing variables in closures show there is useful functionality that
is still not as convenient to "spell" as could be imagined.
It is also useful to find and bind separately. In fact, IMO it's not
separate enough in some cases ;-)

I've wanted something like
x := expr
to spell "find x and rebind it to expr" (or raise NameError if not found).
Extending that to attributes and augassign,
b.a +:= 2
could mean find the "a" attribute, and in whatever attribute dict it's found,
rebind it there. Or raise an Exception for whatever failure is encountered.
This would be nice for rebinding closure variables as well. But it's been discussed,
like most of these things ;-)

Regards,
Bengt Richter
Nov 5 '05 #115
On Thu, 03 Nov 2005 13:37:08 -0500, Mike Meyer <mw*@mired.or g> wrote:
[...]
I think it even less sane, if the same occurce of b.a refers to two
different objects, like in b.a += 2


That's a wart in +=, nothing less. The fix to that is to remove +=
from the language, but it's a bit late for that.

Hm, "the" fix? Why wouldn't e.g. treating augassign as shorthand for a source transformation
(i.e., asstgt <op>= expr becomes by simple text substitution asstgt = asstgt <op> expr)
be as good a fix? Then we could discuss what

b.a = b.a + 2

should mean ;-)

OTOH, we could discuss how you can confuse yourself with the results of b.a += 2
after defining a class variable "a" as an instance of a class defining __iadd__ ;-)

Or point out that you can define descriptors (or use property to make it easy)
to control what happens, pretty much in as much detail as you can describe requirements ;-)

Regards,
Bengt Richter
Nov 5 '05 #116
On 04 Nov 2005 11:04:58 +0100, Stefan Arentz <st***********@ gmail.com> wrote:
Antoon Pardon <ap*****@forel. vub.ac.be> writes:
Op 2005-11-03, Mike Meyer schreef <mw*@mired.org> :
> Antoon Pardon <ap*****@forel. vub.ac.be> writes:
>>> 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.
>
> Except they *don't*. This happens in any language that resolves
> references at run time.


Python doesn't resolve references at run time. If it did the following
should work.

a = 1
def f():
a = a + 1

f()


No that has nothing to do with resolving things at runtime. Your example
does not work because the language is very specific about looking up
global variables. Your programming error, not Python's shortcoming.

If someone has an old version of Python handy, I suspect that it used
to "work", and the "a" on the right hand side was the global "a" because
a local "a" hadn't been defined until the assignment, which worked to
produce a local binding of "a". Personally, I like that better than
the current way, because it follows the order of accesses implied
by the precedences in expression evaluation and statement execution.
But maybe I don't RC ;-)

Regards,
Bengt Richter
Nov 5 '05 #117
bo**@oz.net (Bengt Richter) writes:
Hm, "the" fix? Why wouldn't e.g. treating augassign as shorthand for
a source transformation (i.e., asstgt <op>= expr becomes by simple
text substitution asstgt = asstgt <op> expr) be as good a fix? Then
we could discuss what


Consider "a[f()] += 3". You don't want to eval f() twice.
Nov 5 '05 #118
On 4 Nov 2005 11:09:36 GMT, Antoon Pardon <ap*****@forel. vub.ac.be> wrote:
[...]

Take the code:

lst[f()] += 1

Now let f be a function with a side effect, that in succession
produces the positive integers starting with one.

What do you think this should be equivallent to:

t = f()
lst[t] = lst[t] + 1

or

lst[f()] = lst[f()] + 1

If you think the environment can change between references then I
suppose you prefer the second approach.

I am quite sympathetic to your probe of python semantics, but I
don't think the above is an argument that should be translated
to attribute assignment. BTW, ISTM that augassign (+=) is
a red herring here, since it's easy to make a shared class variable
that is augassigned apparently as you want, e.g.,
class shared(object): ... def __init__(self, v=0): self.v=v
... def __get__(self, *any): return self.v
... def __set__(self, _, v): self.v = v
... class B(object): ... a = shared(1)
... b=B()
b.a 1 B.a 1 b.a += 2
b.a 3 B.a 3 vars(b) {} vars(b)['a'] = 'instance attr'
vars(b) {'a': 'instance attr'} b.a 3 b.a += 100
b.a 103 B.a 103 B.a = 'this could be prevented'
b.a 'instance attr' B.a 'this could be prevented'

The spelled out attribute update works too B.a = shared('alpha')
b.a 'alpha' b.a = b.a + ' beta'
b.a 'alpha beta' B.a 'alpha beta'

But the instance attribute we forced is still there vars(b)

{'a': 'instance attr'}

You could have shared define __add__ and __iadd__ and __radd__ also,
for confusion to taste ;-)

Regards,
Bengt Richter
Nov 5 '05 #119
bo**@oz.net (Bengt Richter) writes:
On Thu, 03 Nov 2005 13:37:08 -0500, Mike Meyer <mw*@mired.or g> wrote:
[...]
I think it even less sane, if the same occurce of b.a refers to two
different objects, like in b.a += 2
That's a wart in +=, nothing less. The fix to that is to remove +=
from the language, but it's a bit late for that.

Hm, "the" fix? Why wouldn't e.g. treating augassign as shorthand for a source transformation
(i.e., asstgt <op>= expr becomes by simple text substitution asstgt = asstgt <op> expr)
be as good a fix? Then we could discuss what

b.a = b.a + 2

should mean ;-)


The problem with += is how it behaves, not how you treat it. But you
can't treat it as a simple text substitution, because that would imply
that asstgt gets evaluated twice, which doesn't happen.
OTOH, we could discuss how you can confuse yourself with the results of b.a += 2
after defining a class variable "a" as an instance of a class defining __iadd__ ;-)
You may confuse yourself that way, I don't have any problems with it
per se.
Or point out that you can define descriptors (or use property to make it easy)
to control what happens, pretty much in as much detail as you can describe requirements ;-)


I've already pointed that out.

<mike
--
Mike Meyer <mw*@mired.or g> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 5 '05 #120

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

106
5601
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?
5
2149
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
5
8732
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
9
1930
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
14
2643
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.
20
4043
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. ...
20
1482
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...
16
3448
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) {}
0
9423
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,...
0
10048
jinu1996
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...
1
9996
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9865
tracyyun
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...
1
7410
isladogs
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...
0
5304
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5447
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3563
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2815
bsmnconsultancy
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...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.