473,756 Members | 1,881 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 8651
On Fri, 04 Nov 2005 08:08:42 +0000, Antoon Pardon wrote:
One other way, to implement the += and likewise operators would be
something like the following.

Assume a getnsattr, which would work like getattr, but would also
return the namespace where the name was found. The implementation
of b.a += 2 could then be something like:

ns, t = getnsattr(b, 'a')
t = t + 2
setattr(ns, 'a')
I'm not arguing that this is how it should be implemented. Just
showing the implication doesn't follow.


Follow the logical implications of this proposed behaviour.

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

def advance(self):
self.current_le vel += 1
py> antoon_game = Game()
py> steve_game = Game()
py> steve_game.adva nce()
py> steve_game.adva nce()
py> print steve_game.leve l
3
py> print antoon_game.lev el

What will it print?

Hint: your scheme means that class attributes mask instance attributes.
--
Steven.

Nov 4 '05 #101
On Fri, 04 Nov 2005 10:48:54 +0000, Antoon Pardon wrote:
Please explain why this is illegal.

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


Because names in function namespaces don't have inheritance.
--
Steven.

Nov 4 '05 #102
On Fri, 04 Nov 2005 09:07:38 +0000, Antoon Pardon wrote:
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.

[snip]
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?


It is each time the 'x' from the same name space. In the code above the
'a' is not each time from the same namespace.

I also think you new very well what I meant.


I'm supposed to be a mindreader now? After you've spent multiple posts
ranting that, quote, "I don't think it is sane that which object is
refered to depends on how many times you already went through the loop",
I'm supposed to magically read your mind and know that you don't actually
object to what you say you object to, but to something completely
different?

--
Steven.

Nov 4 '05 #103
On Fri, 04 Nov 2005 07:46:45 +0000, Antoon Pardon wrote:
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>?
That is an implemantation detail. The only answer that you are given
means nothing more than: because it is implemented that way.


You keep saying "that's an implementation detail" and dismissing the
question, but that's the heart of the issue. What does b.a += 2 *mean*? It
doesn't mean "sort the list referenced by b.a" -- we agree on that much.
You seem to think that it means "increment the object currently named
b.a by two". But that's not what it means.

b.a += 2 has a precise meaning, and for ints and many other objects that
meaning is the same as b.a = b.a + 2. Yes, it is an implementation detail.
So what? It is an implementation detail that "b.a += 2" doesn't mean "sort
the list referenced by b.a" too.

In some other language, that's precisely what it could mean -- but Python
is not that language.

b.a has a precise meaning too, and again you have got it wrong. It doesn't
mean "search b's namespace for attribute a". It means "search b's
namespace for attribute a, if not found search b's class' namespace, and
if still not found, search b's class' superclasses". It is analogous to
nested scopes. In fact, it is a type of nested scope.

In some other language, b.a could mean what you think it means, but Python
is not that language. That's a deliberate design decision. Nested
attribute search gives the most useful results in the most common cases,
while still being easy to work around in the rare cases where it is not
what is wanted.

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 has nothing to do with a model for inheritance, but with a model of
name resolution.


Which is designed to act the way it does in order to produce the
inheritance model. You can't have that inheritance model without that name
resolution.

The hierarchie of searching an instance first in an object and then in
a class isn't that different from searching first in a local namespace
and then in a more global namespace.

When we search names in a function we don't resolve the same name in
different name spacese each occurence of the same name in the same
function occurs in the same namespace.
That's because it isn't needed for function namespaces. Names in a
function don't inherit state or behaviour from names in a higher-level
scope. Attribute names in classes do.

But with class variables we can have that one and the same name
on a line refers to two different namespaces at the same time.
That is IMO madness. You may argue that the madness is of little
importance, you can argue that because of the current implementation
little can be done about it. But I don't see how one can defend
it as sane behaviour.


Because inheritance is useful, sensible, rational behaviour for OO
programming.
--
Steven.

Nov 4 '05 #104
On Fri, 04 Nov 2005 04:42:54 -0800, Paul Rubin wrote:
Steven D'Aprano <st***@REMOVETH IScyber.com.au> writes:
There are good usage cases for the current inheritance behaviour.


Can you name one? Any code that relies on it seems extremely dangerous to me.


Dangerous? In what way?
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
To internationalis e it for the US market:

Paper.size = USLetter

Now create a document using the default paper size:

mydocument = Paper("Four score and seven years ago")
print mydocument.size == USLetter
=> True

Now create a document using another paper size:

page = Paper("Eleventy MILLION dollars")
page.size = Foolscap

Because that's an instance attribute, our default doesn't change:

assert Paper().size == mydocument.size == USLetter
assert page.size != mydocument.size

In case it wasn't obvious, this is the same inheritance behaviour Python
objects exhibit for methods, except that it isn't normal practice to add
methods to instances dynamically. (It is more common to create a
subclass.) But you can do it if you wish, at least for classes you create
yourself.

Objects in Python inherit behaviour from their class.
Objects in Python inherit state from their class, unless their state is
specifically stored in a per-instance basis.
Here's another usage case:

class PrintableWidget (Widget):
prefix = "START "
suffix = " STOP"

def __str__(self):
return self.prefix + Widget.__str__( self) + self.suffix

PrintableWidget s now print with a default prefix and suffix, which can be
easily changed on a per-instance basis without having to create
sub-classes for every conceivable modification:

english_gadget = PrintableWidget ("data")
print english_gadget
=> prints "START data STOP"

dutch_gadget = PrintableWidget ("data")
dutch_gadget.pr efix = "BEGIN "
dutch_gadget.su ffix = " EINDE"
print dutch_gadget
=> prints "BEGIN data EINDE"


I have to ask... did OO programming suddenly fall out of favour when my
back was turned? People still use C++, C#, Objective-C and Java, right?
Why are so many folks on this list having trouble with inheritance? Have I
missed something?
--
Steven.

Nov 4 '05 #105
On 4 Nov 2005 08:23:05 GMT, Antoon Pardon <ap*****@forel. vub.ac.be> wrote:
Op 2005-11-03, Magnus Lycka schreef <ly***@carmen.s e>:
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.


Then couldn't we expect that the namespace resolution is also done
only once?

I say that if the introduction on += like operators implied that the
same mentioning of a name would in some circumstances be resolved to
two different namespaces, then such an introduction would better have
not occured.

Would it be too much to ask that in a line like.

x = x + 1.

both x's would resolve to the same namespace?

I think I would rather seek consistency in terms of
order of evaluation and action. IOW, the right hand side
of an assignment is always evaluated before the left hand side,
and operator precedence and syntax defines order of access to names
in their expression context on either side.

The compilation of function bodies violates the above, even allowing
future (execution-wise) statements to influence the interpretation
of prior statements. This simplifies defining the local variable set,
and allows e.g. yield to change the whole function semantics, but
the practicality/purity ratio makes me uncomfortable ;-)

If there were bare-name properties, one could control the meaning
of x = x + 1 and x += 1, though of course one would need some way
to bind/unbind the property objects themselves to make them visible
as x or whatever names.

It might be interesting to have a means to push and pop objects
onto/off-of a name-space-shadowing stack (__nsstack__), such that the first place
to look up a bare name would be as an attribute of the top stack object, i.e.,

name = name + 1

if preceded by

__nsstack__.app end(my_namespac e_object)

would effectively mean

my_namespace_ob ject.name = my_namespace_ob ject.name + 1

by way of logic like

if __nsstack__:
setattr(__nssta ck__[-1], getattr(__nstac k__[-1], name) + 1))
else:
x = x + 1
Of course, my_namespace_ob ject could be an instance of a class
that defined whatever properties or descriptors you wanted.
When you were done with that namespace, you'd just __nsstack__.pop ()

If __nsstack__ is empty, then of course bare names would be looked
up as now.

BTW, __nsstack__ is not a literal proposal, just a way to illustrate the concept ;-)
OTOH, is suppose a function could have a reseved slot for a name space object stack
that wouldn't cost much run time to bypass with a machine language check for NULL.

BTW2, this kind of stack might play well with a future "with," to guarantee name
space popping. Perhaps "with" syntax could even be extended to make typical usage
slick ;-)

Regards,
Bengt Richter
Nov 4 '05 #106
Bengt Richter wrote:

It might be interesting to have a means to push and pop objects
onto/off-of a name-space-shadowing stack (__nsstack__), such that the first place
to look up a bare name would be as an attribute of the top stack object, i.e.,

name = name + 1


Don't be that specific; just unify Attributes and Names.

Instead of the 'name' X referring to locals()['X'] or globals()['X'],
have a hidden "namespace" object/"class", with lookups functioning akin
to class inheritence.

This would allow, in theory, more uniform namespace behaviour with outer
scoping:

x = 1
def f():
x += 1 # would work, as it becomes
setattr(namespa ce,'x',getattr( namespace,'x')+ 1), just like attribute loookup

Also, with a new keyword "outer", more rational closures would work:

def makeincr(start= 0):
i = start
def inc():
outer i
j = i
i += 1
return j
return inc

From a "namespace object" point of view, 'outer i' would declare i to
be a descriptor on the namespace object, such that setting actions would
set the variable in the inherited scope (getting actions wouldn't
actually need modification, since it already falls-through). At the
first level, 'outer' would be exactly the same as 'global' -- indeed, it
would be reasonable for the outer keyword to entirely replace global
(which is actually module-scope).

As it stands, the different behaviours of names and attributes is only a
minor quirk, and the fix would definitely break backwards compatibility
in the language -- it'd have to be punted to Py3k.
Nov 4 '05 #107
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.
Nov 4 '05 #108
Paul Rubin <http://ph****@NOSPAM.i nvalid> writes:
Mike Meyer <mw*@mired.or g> writes:
I've already argued that the kludges suggested to "solve" this problem
create worse problems than this.

The most obvious solution is to permit (or even require) the
programmer to list the instance variables as part of the class
definition. Anything not in the list is not an instance variable,
i.e. they don't get created dynamically. That's what most other
languages I can think of do. Some Python users incorrectly think this
is what __slots__ does, and try to use __slots__ that way. That they
try to do that suggests that the approach makes some sense.


That breaks the ability to add attributes dynamically, which is
usefull. If you need an extra piece of data with some existing class,
it's much easier to just add an attribute to hold it than to create a
subclass for the sole purpose of adding that attribute.

<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 #109
Antoon Pardon <ap*****@forel. vub.ac.be> writes:
Op 2005-11-04, Mike Meyer schreef <mw*@mired.org> :
Would it be too much to ask that in a line like.

x = x + 1.

both x's would resolve to the same namespace?


Yes. That's to much bondage for programmers who've become accustomed
to freedom. Explain why this should be illegal:
> class C:

... def __getattr__(sel f, name):
... x = 1
... return locals()[name]
... def __setattr__(sel f, name, value):
... globals()[name] = value
...
> o = C()
> o.x = o.x + 1
> x

2


I'll answer with a contra question.

Please explain why this is illegal.

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

f()


It isn't illegal, it just requires a different syntax.

<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 #110

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

Similar topics

106
5589
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
2148
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
2641
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
4042
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
1480
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
3445
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
9462
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
10046
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
9886
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
9857
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
8723
agi2029
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...
1
7259
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
5155
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...
1
3817
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
3
2677
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.