473,769 Members | 1,803 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 8666
On Fri, 04 Nov 2005 18:20:56 -0500, Mike Meyer wrote:
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?


We could argue about details of a throw away line for hours :-)

What I meant was, there is the way Python does it, and then there are (or
were) interpreters that when faced with a block like this:

for i in range(10):
print i

parses "print i" ten times.

It doesn't really matter whether any interpreters back in the 1970s were
actually that bad, or just toy interpreters as taught about in undergrad
university courses.
--
Steven.

Nov 5 '05 #121
On Fri, 04 Nov 2005 09:24:41 -0500, Christopher Subich <cs************ ****@spam.subic h.block.com> wrote:
Steven D'Aprano 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 b.a += 2 expands to b.a = b.a + 2. Why would you want b.a =
<something> to correspond to b.__class__.a = <something>?


Small correction, it expands to b.a = B.a.__class__._ _iadd__(b.a,2),
assuming all relevant quantities are defined. For integers, you're
perfectly right.

But before you get to that, a (possibly inherited) type(b).a better
not have a __get__ method trumping __class__ and the rest ;-)

Regards,
Bengt Richter
Nov 5 '05 #122
On Fri, 04 Nov 2005 16:06:45 -0800, Paul Rubin wrote:
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?

Documents which don't care what paper size they are will automatically use
the default paper size on whatever system they are opened under. Send them
to somebody in the US, and they will use USLetter. Send to someone in
Australia, and they will use A4.

In any case, even if you conclude that there is little benefit to
inheritance in this particular example, the principle is sound:
sometimes you gain benefit by inheriting state.

--
Steven.

Nov 5 '05 #123
On 04 Nov 2005 17:53:34 -0800, Paul Rubin <http://ph****@NOSPAM.i nvalid> wrote:
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.


Well, if you accepted macro semantics IWT you _would_ want to ;-)

Hm, reminds me of typical adding of parens in macros to control precedence
in expressions ... so I tried
a = [0]
(a[0]) += 1

SyntaxError: augmented assign to tuple literal or generator expression not possible

;-/

Regards,
Bengt Richter
Nov 5 '05 #124
On Fri, 04 Nov 2005 10:28:52 -0500, Christopher Subich <cs************ ****@spam.subic h.block.com> wrote:
Antoon Pardon wrote:
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


This isn't an implementation detail; to leading order, anything that
impacts the values of objects attached to names is a specification issue.

An implementation detail is something like when garbage collection
actually happens; what happens to:

b.a += 2

is very much within the language specification. Indeed, the language
specificatio n dictates that an instance variable b.a is created if one
didn't exist before; this is true no matter if type(b.a) == int, or if
b.a is some esoteric mutable object that just happens to define
__iadd__(self, type(other) == int).

But if it is an esoteric descriptor (or even a simple property, which is
a descriptor), the behaviour will depend on the descriptor, and an instance
variable can be created or not, as desired, along with any side effect you like.

Regards,
Bengt Richter
Nov 5 '05 #125
On Sat, 05 Nov 2005 00:25:34 +0000, Bengt Richter wrote:
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:


Think about *what* b.a += 2 does, not *how* it does it. Perhaps for some
other data type it would make a difference whether the mechanism was
BINARY_ADD (__add__) or INPLACE_ADD (__iadd__), but in this case it does
not. Both of them do the same thing.

Actually, no "perhaps" about it -- we've already discussed the case of
lists.

Sometimes implementation makes a difference. I assume BINARY_ADD and
INPLACE_ADD work significantly differently for lists, because their
results are significantly (but subtly) different:

py> L = [1,2,3]; id(L)
-151501076
py> L += [4,5]; id(L)
-151501076
py> L = L + []; id(L)
-151501428
But all of this is irrelevant to the discussion about binding b.a
differently on the left and right sides of the equals sign. We have
discussed that the behaviour is different with mutable objects, because
they are mutable -- if I recall correctly, I was the first one in this
thread to bring up the different behaviour when you append to a list
rather than reassign, that is, modify the class attribute in place.

I'll admit that my choice of terminology was not the best, but it wasn't
misleading. b.a += 2 can not modify ints in place, and so the
effect of b.a += 2 is the same as b.a = b.a + 2, regardless of what
byte-codes are used, or even what C code eventually implements that
add-and-store.

In the case of lists, setting Class.a = [] and then calling instance.a +=
[1] would not exhibit the behaviour Antoon does not like, because the
addition is done in place. But calling instance.a = instance.a + [1]
would.

My question still stands: why would you want instance.a = <something>
to operate as instance.__clas s__.a = <something>?
--
Steven.

Nov 5 '05 #126
On Fri, 04 Nov 2005 13:52:22 -0800, 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.


It might be bogus to you, but it isn't to me. I prefer to delay setting
instance attributes until they are needed.

It also allows you to do something like this:

class ExpertGame(Game ):
current_level = 100
and then use ExpertGame anywhere you would have used Game with no problems.

Yes, there are other ways to do this. I won't say they are wrong, but I
don't believe they are better.

--
Steven.

Nov 5 '05 #127
On Fri, 04 Nov 2005 12:10:11 +0000, Antoon Pardon wrote:
There are good usage cases for the current inheritance behaviour. I asked
before what usage case or cases you have for your desired behaviour, and
you haven't answered. Perhaps you missed the question? Perhaps you haven't
had a chance to reply yet? Or perhaps you have no usage case for the
behaviour you want.


There are good use cases for a lot of things python doesn't provide.
There are good use cases for writable closures, but python doesn't
provide it, shrug, I can live with that. Use cases is a red herring
here.


Is that a round-about way of saying that you really have no idea of
whether, how or when your proposed behaviour would be useful?

Personally, I think that when you are proposing a major change to a
language that would break the way inheritance works, there should be more
benefits to the new way than the old way.

Some things are a matter of taste: should CPython prefer <> or != for not
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?

The behaviour you are calling "insane" is partly a matter of taste, but it
is mostly a matter of objective fact. I believe that the standard
model for inheritance that you call insane is rational because it is
useful in far more potential and actual pieces of code than the behaviour
you prefer -- and the designers of (almost?) all OO languages seem to
agree with me.


I didn't call the model for inheritance insane.


Antoon, I've been pedanted at by experts, and you ain't one. The behaviour
which you repeatedly described as not sane implements the model for
inheritance. The fact that you never explicitly said "the standard OO
model of inheritance" cuts no ice with me, not when you've written
multiple posts saying that the behaviour of that standard inheritance
model is not sane.

The standard behaviour makes it easy for code to do the right thing in
more cases, without the developer taking any special steps, and in the
few cases where it doesn't do the right thing (e.g. when the behaviour
you want is for all instances to share state) it is easy to work
around. By contrast, the behaviour you want seems to be of very limited
usefulness, and it makes it difficult to do the expected thing in
almost all cases, and work-arounds are complex and easy to get wrong.


Please don't make this about what I *want*. I don't want anything. I
just noted that one and the same reference can be processed multiple
times by the python machinery, resulting in that same reference
referencing differnt variables at the same time and stated that that was
unsane behaviour.


"Unsane" now?

Heaven forbid that I should criticise people for inventing new words, but
how precisely is unsane different from insane? In standard English,
something which is not sane is insane.

The standard behaviour makes it easy for objects to inherit state, and
easy for them to over-ride defaults. The behaviour(s) you and Graham
want have awkward side-effects: your proposed behaviour would mean that
class attributes would mask instance attributes, or vice versa, meaning
that the programmer would have to jump through hoops to get common
types of behaviour like inheriting state.


You don't know what I want. You only know that I have my criticism of
particular behaviour. You seem to have your idea about what the
alternative would be like, and project that to what I would want.


Well now is a good time for you to stop being so coy and tell us what you
want. You don't like the current behaviour. So what is your alternative?
I've given you some suggestions for alternative behaviour. You've refused
to say which one you prefer, or suggest your own.

If you're just trolling, you've done a great job of it because you fooled
me well and good. But if you are serious in your criticism about the
behaviour, then stop mucking about and tell us what the behaviour should
be. Otherwise your criticism isn't going to have any practical effect on
the language at all.
That's an objective claim: please explain what makes your behaviour
more rational than the standard behaviour. Is your behaviour more
useful? Does it make code easier to write? Does it result in more
compact code? What usage cases?


What my behaviour? I don't need to specify alternative behaviour in
order to judge specific behaviour.


If you are serious about wanting the behaviour changed, and not just
whining, then somebody has to come up with an alternative behaviour that
is better. If not you, then who? Most of the folks who have commented on
this thread seem to like the existing behaviour.

--
Steven.

Nov 5 '05 #128

Nov 5 '05 #129
Steven D'Aprano <st***@REMOVETH IScyber.com.au> writes:
It also allows you to do something like this:

class ExpertGame(Game ):
current_level = 100 and then use ExpertGame anywhere you would have used Game with no problems.


Well, let's say you set, hmm, current_score = 100 instead of current_level.
Scores in some games can get pretty large as you get to the higher
levels, enough so that you start needing long ints, which maybe are
used elsewhere in your game too, like for the cryptographic signatures
that authenticate the pieces of treasure in the dungeon. Next you get
some performance gain by using gmpy to handle the long int arithmetic,
and guess what? Eventually a version of your game comes along that
enables the postulated (but not yet implemented) mutable int feature
of gmpy for yet more performance gains. So now, current_score += 3000
increments the class variable instead of creating an instance
variable, and whoever maintains your code by then now has a very weird
bug to track down and fix.

Anyway, I'm reacting pretty badly to the construction you're
describing. I haven't gotten around to looking at the asyncore code
but will try to do so.
Nov 5 '05 #130

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

Similar topics

106
5600
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
9589
marktang
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...
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
10212
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9863
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?
1
3962
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3563
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.