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.
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.
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.
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?
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
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
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 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.
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 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. 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: 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: 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,...
| |
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: 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: 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...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
|
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...
| |