Re: variable scope of class objects

2015-10-22 Thread Luca Menegotto

Il 20/10/2015 23:33, JonRob ha scritto:



Hello Luca,

I very much appreciated your comments.  And I understand the
importance of "doing something right"  (i.e. convention).

This leads me to another question.

Because I am interfacing with an I2C sensor I have many register
definations to include (30 register addresses and  26 Variables to be
red from some of those registers.
In your comment you mentioned that convention is to declare variables
(and constants?)  in the construction (__ini__).
I am concerned that the sheer number of varialbe / constants would
make it difficult to read.

In your opinion, what would be the best method to structure such code?

Regards
JonRob


Let's start from constants. Constants, in Python, simply don't exist 
(and IMHO this is one of the few lacks of Python). All you can do is to 
declare a variable and treat it as a constant: you never change it!


It doesn't make sense to put a constant declaration at instance level, 
declaring it in the __init__ part of a class. After all, a constant is 
an information you want to share. The choice is up to you as the project 
manager: if you think that your constant is deeply related to the class 
you're designing, declare it as a class variable; otherwise, declare it 
at global level (in this case, often I use a separate file dedicated to 
constant declaration).


--
Ciao!
Luca


--
https://mail.python.org/mailman/listinfo/python-list


Re: variable scope of class objects

2015-10-22 Thread Erik

On 20/10/15 22:33, jon...@mail.python.org wrote:

In your comment you mentioned that convention is to declare variables
(and constants?)  in the construction (__ini__).


I would suggest that 'constants' are not 'declared' in the __init__ 
method body, but either as class variables or (see later) at module scope.



I am concerned that the sheer number of varialbe / constants would
make it difficult to read.


Remember that "instance variables" in Python are just name bindings to 
another object which are placed in the object's dictionary.


Python is not like some other languages where you declare your object's 
member variables statically and they all magically exist when you create 
the object (whether you initialise them or not): none of the bindings 
exist until an assignment is executed.


Therefore, you _must_ have a set of assignments which are executed to 
create the object with the bindings (or "instance variables") that you 
require. This is _usually_ done in __init__ with a set of assignments to 
'self' - either using default values or values passed in to __init__.




You may be getting to the point where the best way to structure this is 
to write your own module (rather than just a class) which you then 
import from your main script. For example, you might do something like this:


mymodule.py:

CONSTANT_X = 0x99
CONSTANT_Y = 0xF00
CONSTANT_Z = "Spam"

class MyObject(object):
def __init__(self, foo, bar):
# 'foo' can be anything. 'bar' must be one of
# a specific set of values:
if bar not in (CONSTANT_X, CONSTANT_Y):
raise ValueError("Parameter 'bar'")

self.foo = foo
self.bar = bar

Then, in your main script you might do something like:

import mymodule

obj = mymodule.MyObject(100, mymodule.CONSTANT_X)

... then start calling methods on 'obj'.

So you just define your address and variable constants at module level 
and import them along with any class and function definitions.


E.
--
https://mail.python.org/mailman/listinfo/python-list


Re: variable scope of class objects

2015-10-22 Thread Luca Menegotto

Maybe I've been too cryptic. I apologize.

Il 22/10/2015 01:35, JonRob ha scritto:

@Dennis,


Thanks for your example.  My structure is very similar.


And that's ok. But you can also 'attach' the constants to a class, if it 
makes sense. For example, the same code of Dennis can be written as:


class SensorA():
GYROXREG = 0x0010
GYROYREG = 0x0011
GYROZREG = 0x0001
_registers = [GYROXREG, GYROYREG, GYROZREG]

And then you can invoke those constants as:

SensorA.GYROXREG

to emphasize that they are significant to this class, and to this class 
only.



 Luca wrote...

Please, note that declaring a variable in the constructor is only a
convention: in Python you can add a variable to an object of a class
wherever you want in your code (even if it is very dangerous and
discouraged).


This is the cryptic part.
I mean: you can do, and it's perfectly legal:

class A():
def __init__(self):
self.a = 10

if __name__ == '__main__':
o = A()
print(o.a)
# this is a new member, added on the fly
o.b = 20
print(o.b)

but, for God's sake, use it only if you have a gun at your head!

--
Ciao!
Luca

--
https://mail.python.org/mailman/listinfo/python-list


Re: variable scope of class objects

2015-10-21 Thread JonRob
@Dennis,


Thanks for your example.  My structure is very similar.  Perhaps I was
reading too much into Luca's below statement regarding declaring
variables.

Regards,
JonRob




Luca wrote...
>Please, note that declaring a variable in the constructor is only a 
>convention: in Python you can add a variable to an object of a class 
>wherever you want in your code (even if it is very dangerous and 
>discouraged).


 





On Tue, 20 Oct 2015 20:18:35 -0400, Dennis Lee Bieber
 wrote:

>On Tue, 20 Oct 2015 17:33:21 -0400, jon...@mail.python.org declaimed the
>following:
>
>>
>>
>>Hello Luca,
>>
>>I very much appreciated your comments.  And I understand the
>>importance of "doing something right"  (i.e. convention).
>>
>>This leads me to another question.
>>
>>Because I am interfacing with an I2C sensor I have many register
>>definations to include (30 register addresses and  26 Variables to be
>>red from some of those registers.
>>In your comment you mentioned that convention is to declare variables
>>(and constants?)  in the construction (__ini__).
>>I am concerned that the sheer number of varialbe / constants would
>>make it difficult to read.
>>
>
>   "Constants" are typically defined at module level, using all capitals
>as a hint to the reader (Python does not have anything that one might
>consider a true constant -- other than the language defined singletons:
>None, and maybe by now True and False).
>
>   Register addresses are likely "constants". Not sure about your "26
>Variables"... Do they map directly to registers, or are they extracted as
>fields from the values returned -- that is, a register may have two or more
>"variables"? Do you read ALL registers on command and hold the values (note
>my usage -- values can be held in lists or dictionaries using a single
>"variable") for later retrieval by the user, or only read A register on
>command by the user and return that value.
>
>-=-=-=-=-
>#  registers for a fictitious motion sensor
>GYROXREG = 0x0010
>GYROYREG = 0x0011
>GYROZREG = 0x0001
>...
>MAGZREG = 0x0100
>
>class SensorA(I2C):#I'm assuming class I2C provides read/write functions
>   _registers = [GYROXREG, GYROYREG, GYROZREG,
>   ..., MAGZREG]
>   def __init__(self, SCLpin, SDApin, slaveAddress):
>   self._SCL = SCLpin
>   self._SDA = SDApin
>   self._addr = slaveAddress
>   self.update()   #initial load of values
>   def update(self):
>   #basically a loop over all addresses
>   #I'm not going to try to pseudo code the full I2C protocol
>   self.values = {}#yes, a dictionary
>   for reg in _registers:
>   aValue = self.read(self._SCL, self._SDA, self._addr, 
> reg)
>   #inherited from I2C class
>   self.values[reg] = aValue
>
>
>mySensor = SensorA(21, 22, 0x6)
>
>while True
>   mySensor.update()
>   print ("Gyro X: %s, Y: %s, Z: %s"
>   % (mySensor.values[GYROXREG],
>   mySensor.values[GYROYREG],
>   mySensor.values[GYROZREG]))
>   time.sleep(1.0)
>
>
>   
>   
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: variable scope of class objects

2015-10-20 Thread Luca Menegotto

Il 19/10/2015 20:39, JonRob ha scritto:


I (think) I understand that in the below case, the word self could be
replaced with "BME280" to explicitly call out a variable.

But even still I don't know how explicit call out effects the scope of
a variable.


These two statements make me think you come from C++ or something similar.

In Python you can declare variables at class level, but this declaration 
must NOT be interpreted in the same manner of a similar declaration in 
C++: they remain at the abstract level of a class, and they have nothing 
to do with an instance of a class (in fact, to be correctly invoked, 
they must be preceeded by the class name).


'self' (or a similar representation, you could use 'this' without 
problem) gives you access to the instance of the class, even in the 
constructor; it is important, because the constructor is the place where 
instance variables should be defined. Something like this:


class foo:
# invoke with foo._imAtClassLevel
_imAtClassLevel = 10

def __init__(self):
#  need to say how this must be invoked?
self._imAtInstanceLevel = 0

no confusion is possible, because:

class foo2:
_variable = 1000

def __init__(self):
# let's initialize an instance variable with
# a class variable
self._variable = foo2._variable

Please, note that declaring a variable in the constructor is only a 
convention: in Python you can add a variable to an object of a class 
wherever you want in your code (even if it is very dangerous and 
discouraged).


--
Ciao!
Luca

--
https://mail.python.org/mailman/listinfo/python-list


Re: variable scope of class objects

2015-10-20 Thread Luca Menegotto

Il 20/10/2015 08:38, Nagy László Zsolt ha scritto:


When you say "they have nothing to do", it is almost true but not 100%.


I know it, but when it comes to eradicate an idea that comes directly 
from C++-like languages, you must be drastic.

Nuances come after...

--
Ciao!
Luca
--
https://mail.python.org/mailman/listinfo/python-list


Re: variable scope of class objects

2015-10-20 Thread Nagy László Zsolt

> These two statements make me think you come from C++ or something
> similar.
>
> In Python you can declare variables at class level, but this
> declaration must NOT be interpreted in the same manner of a similar
> declaration in C++: they remain at the abstract level of a class, and
> they have nothing to do with an instance of a class (in fact, to be
> correctly invoked, they must be preceeded by the class name).
When you say "they have nothing to do", it is almost true but not 100%.

When accessing attributes of an instance, Python first searches in the
namespace of the instance. When not found, it searches in the namespace
of its class.

So for example:

>>>
>>> class A(object):
... a = ["value 1"]
... def set_a(self):
... # This will bind the value  to the name "a" in the namespace
of the instance (!!!), not the class
... self.a = ["value 3"]
...
>>> a = A()
>>> b = A()
>>> print A.a # ["value 1"]
['value 1']
>>> print a.a  # ["value 1"]
['value 1']
>>> print b.a  # ["value 1"]
['value 1']
>>> A.a.append("value 2")
>>> print A.a # ["value 1","value 2"]
['value 1', 'value 2']
>>> print a.a  # ["value 1","value 2"]
['value 1', 'value 2']
>>> print b.a  # ["value 1","value 2"]
['value 1', 'value 2']
>>> a.set_a()
>>> print a.a  # ["value 3"]
['value 3']
>>> print A.a # ["value 1","value 2"]
['value 1', 'value 2']
>>> print b.a # ["value 1","value 2"]
['value 1', 'value 2']
>>> print A.a is b.a # True
True
>>> print a.a is b.a # False
False
>>> b.a.append("value 4")
>>> A.a
['value 1', 'value 2', 'value 4']
>>> del a.a
>>> a.a
['value 1', 'value 2', 'value 4']
>>>

Some objects are designed this way: the attribute with the same name can
be bound to an object stored at class level or at instance level,
depending on how the object was created or used. In other words: when
you access an attrbute through an object, you can very well reach a
class attribute instead of an object attribute; and this behaviour can
be different for different instances of the same class. Just look at the
last attribute deletion - by deleting an attribute of an instance,
further attribute access will hit the class level object. The same
behaviour is unthinkable with C++.




-- 
https://mail.python.org/mailman/listinfo/python-list


Re: variable scope of class objects

2015-10-20 Thread JonRob


Hello Luca,

I very much appreciated your comments.  And I understand the
importance of "doing something right"  (i.e. convention).

This leads me to another question.

Because I am interfacing with an I2C sensor I have many register
definations to include (30 register addresses and  26 Variables to be
red from some of those registers.
In your comment you mentioned that convention is to declare variables
(and constants?)  in the construction (__ini__).
I am concerned that the sheer number of varialbe / constants would
make it difficult to read.

In your opinion, what would be the best method to structure such code?

Regards
JonRob




On Tue, 20 Oct 2015 08:17:16 +0200, Luca Menegotto
 wrote:

>Il 19/10/2015 20:39, JonRob ha scritto:
>
>> I (think) I understand that in the below case, the word self could be
>> replaced with "BME280" to explicitly call out a variable.
>>
>> But even still I don't know how explicit call out effects the scope of
>> a variable.
>
>These two statements make me think you come from C++ or something similar.
>
>In Python you can declare variables at class level, but this declaration 
>must NOT be interpreted in the same manner of a similar declaration in 
>C++: they remain at the abstract level of a class, and they have nothing 
>to do with an instance of a class (in fact, to be correctly invoked, 
>they must be preceeded by the class name).
>
>'self' (or a similar representation, you could use 'this' without 
>problem) gives you access to the instance of the class, even in the 
>constructor; it is important, because the constructor is the place where 
>instance variables should be defined. Something like this:
>
>class foo:
> # invoke with foo._imAtClassLevel
> _imAtClassLevel = 10
>
> def __init__(self):
> #  need to say how this must be invoked?
> self._imAtInstanceLevel = 0
>
>no confusion is possible, because:
>
>class foo2:
> _variable = 1000
>
> def __init__(self):
> # let's initialize an instance variable with
> # a class variable
> self._variable = foo2._variable
>
>Please, note that declaring a variable in the constructor is only a 
>convention: in Python you can add a variable to an object of a class 
>wherever you want in your code (even if it is very dangerous and 
>discouraged).
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: variable scope of class objects

2015-10-20 Thread JonRob
Thanks to all who replied to my question.   I received a lot of
information and points of view that are very helpful.   I realize some
of you folks spent more that a few minutes.  I really appreciate your
time.

Pardon me that i replied to random832's post and not the original but
my original was lost while I was trying to bookmark it.


Regards,
JonRob



On Mon, 19 Oct 2015 15:01:14 -0400, Random832 
wrote:

>jon...@mail.python.org writes:
>>
>> The below pseudo code is distilled from my 1st attempt at a functional
>> Python program on the RasPi.
>>
>> My questions are:
>> What is the scope of class variables?
>
>You must access them as members of the class or an instance of the class.
>
>> does the self. prefix modify this scope?
>
>self just refers to the instance of the class that the function was
>called with. It can be any name.
>
>Python automatically transforms any reference to "[object].func" into a
>function (specifically, a bound method object) that will prefix [object]
>to the argument list of the defined function.
>
>> #!/usr/bin/python
>> # -- developed using Python 2.7.3
>>
>> class BME280:
>>
>> # all the below are class variables
>> # those preceded by an underscore are predefined to some constant
>
>Constants should be in uppercase, not prefixed with an underscore.
>
>Names prefixed with an underscore imply that they are "private" (not
>really) and therefore other code should not use them directly
>
>> # those without the underscore are to be "working" variables.
>
>I don't know what you mean by "working".
>
>>
>> _regT1   = 0x88
>> _regH6   = 0xE7
>> _coeff_P2= 0x82
>> _coeff_P6= 0x32
>> 
>> filter   = 0#should these be "self"?
>> t_fine   = 0
>
>I don't know, should they? If so they need to be in __init__.
>
>You haven't provided any functions that use them, so it's not clear what
>they're for.
>
>> 
>> def __init__(self, address=0x76, debug=True):
>> self.i2c = Adafruit_I2C(address)
>> self.address = address
>> self.debug = debug
>> 
>> def pressure_calc(self):
>> var1 = self.i2c.readU16(self._regT1,False)
>> p = (1048576.0 - var1) * _coeff_P2
>> return p
>> 
>> def read_pressure(self):  #called  by main application
>> pressure_hPa = pressure_calc(self) /10 
>> # apply compensation
>> return pressure_hPa
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: variable scope of class objects

2015-10-19 Thread Random832
jon...@mail.python.org writes:
>
> The below pseudo code is distilled from my 1st attempt at a functional
> Python program on the RasPi.
>
> My questions are:
> What is the scope of class variables?

You must access them as members of the class or an instance of the class.

> does the self. prefix modify this scope?

self just refers to the instance of the class that the function was
called with. It can be any name.

Python automatically transforms any reference to "[object].func" into a
function (specifically, a bound method object) that will prefix [object]
to the argument list of the defined function.

> #!/usr/bin/python
> # -- developed using Python 2.7.3
>
> class BME280:
>
> # all the below are class variables
> # those preceded by an underscore are predefined to some constant

Constants should be in uppercase, not prefixed with an underscore.

Names prefixed with an underscore imply that they are "private" (not
really) and therefore other code should not use them directly

> # those without the underscore are to be "working" variables.

I don't know what you mean by "working".

>
> _regT1   = 0x88
> _regH6   = 0xE7
> _coeff_P2= 0x82
> _coeff_P6= 0x32
> 
> filter   = 0#should these be "self"?
> t_fine   = 0

I don't know, should they? If so they need to be in __init__.

You haven't provided any functions that use them, so it's not clear what
they're for.

> 
> def __init__(self, address=0x76, debug=True):
> self.i2c = Adafruit_I2C(address)
> self.address = address
> self.debug = debug
> 
> def pressure_calc(self):
> var1 = self.i2c.readU16(self._regT1,False)
> p = (1048576.0 - var1) * _coeff_P2
> return p
> 
> def read_pressure(self):  #called  by main application
> pressure_hPa = pressure_calc(self) /10 
> # apply compensation
> return pressure_hPa

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: variable scope of class objects

2015-10-19 Thread Terry Reedy

On 10/19/2015 7:19 PM, sohcahto...@gmail.com wrote:


Class variables are accessible without creating an instance of a class.  Also, 
changing the value of a class variable affects ALL instances of that class.  
This is because the variable belongs to the class itself, not any of the 
instances of that class.

"self" is used to tell the interpreter that the variable/function you are 
accessing is a member of an instance of that class.


Wrong.  The first parameter of a method is an instance of a class.  It 
is conventionally called 'self' but could be any other name.  I use 's' 
for quick private test examples.



Here's an example:

class MyObject(object):
 count = 0
 def __init__(value):


This should be def __init__(self, value):


 MyObject.count += 1
 self.value = value

 def printStuff():


  def print(self):


 print("My value is ", self.value)


> a = MyObject('a')
In 2.7.10
TypeError: __init__() takes exactly 1 argument (2 given)
Please run code before posting.

--
Terry Jan Reedy

--
https://mail.python.org/mailman/listinfo/python-list


Re: variable scope of class objects

2015-10-19 Thread sohcahtoa82
On Monday, October 19, 2015 at 11:39:59 AM UTC-7, JonRob wrote:
> Hi,
> 
> I've having trouble understanding the self concept as it applies to
> variables.  I think I understand how it affects methods.
> 
> I haven't been able to fully grasp the scope of class variables and
> the effect of the "self"  to the scope of the variable.
> 
> I (think) I understand that in the below case, the word self could be
> replaced with "BME280" to explicitly call out a variable.
> 
> But even still I don't know how explicit call out effects the scope of
> a variable.
> 
> The below pseudo code is distilled from my 1st attempt at a functional
> Python program on the RasPi.
> 
> My questions are:
> What is the scope of class variables?
> does the self. prefix modify this scope?
> 
> Thanks
> 
> Regards
> 
> JonRob
> 
> 
> 
> 
> #!/usr/bin/python
> # -- developed using Python 2.7.3
> 
> class BME280:
> 
> # all the below are class variables
> # those preceded by an underscore are predefined to some constant
> # those without the underscore are to be "working" variables.
> 
> _regT1   = 0x88
> _regH6   = 0xE7
> _coeff_P2= 0x82
> _coeff_P6= 0x32
> 
> filter   = 0#should these be "self"?
> t_fine   = 0
> 
> def __init__(self, address=0x76, debug=True):
> self.i2c = Adafruit_I2C(address)
> self.address = address
> self.debug = debug
> 
> def pressure_calc(self):
> var1 = self.i2c.readU16(self._regT1,False)
> p = (1048576.0 - var1) * _coeff_P2
> return p
> 
> def read_pressure(self):  #called  by main application
> pressure_hPa = pressure_calc(self) /10 
> # apply compensation
> return pressure_hPa

Class variables are accessible without creating an instance of a class.  Also, 
changing the value of a class variable affects ALL instances of that class.  
This is because the variable belongs to the class itself, not any of the 
instances of that class.

"self" is used to tell the interpreter that the variable/function you are 
accessing is a member of an instance of that class.

Here's an example:

class MyObject(object):
count = 0
def __init__(value):
MyObject.count += 1
self.value = value

def printStuff():
print("My value is ", self.value)

print(MyObject.count)   # This will print 0
a = MyObject('a')
print(MyObject.count)   # This will print 1
print(a.count)  # This will also print 1
a.printStuff()  # This will print "My value is a"
b = MyObject('b')
print(a.count)  # This will print 2
print(b.count)  # This will also print 2
b.printStuff()  # This will print "My value is b"
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: variable scope of class objects

2015-10-19 Thread Nagy László Zsolt

>
> #!/usr/bin/python
> # -- developed using Python 2.7.3
>
> class BME280:

Not strictly related to the question, but you probably want to use so
called "new style classes" when developing a new program for Python
version 2. In other words, use:

class BME280(object):

instead of

class BME280:


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: variable scope of class objects

2015-10-19 Thread Nagy László Zsolt

> My questions are:
> What is the scope of class variables?
In Python, you bind values (objects) to names. It is conceptually
different from "setting the value of a variable". In Python, scope
applies to names, not variables.

When you say "class variable", what do you mean?

This may help:

A namespace is just a dictionary that binds names to objects. AFAIK
there are three kinds of namepaces: local, global and namespaces of
other programming tools that can define their own namespaces. Namely:
eache modul and class defines its own namespace. So if you bind a name
to an object at module level, then that name will be put into the
module's namespace. When you bind a name inside a class, for example:

class A(object):
example_name = 5

then the name "example_name" will be placed in the namespace of the
class, and it can be accessed using the class. E.g. "A.example_name".

The so called local namespace belongs to functions and methods being
called. Any name that is assigned locally inside a method will be a
local name of that method, and it will be visible from that method only
- except if you explicitely tell that it should be global using the
"global" keyword. Formal parameters of methods are also local names, but
they get assigned a value when the method is called. The process of
assigning actucal objects for formal parameters is called binding. When
binding is done, the parameters will become "actual parameters" or
"arguments" that have an actual object assigned. Please note the
difference between formal parameters and arguments:

  * Formal parameters are syntactical. They do not have an object
(value) assigned.
  * Arguments are objects bound to formal parameters. They do have an
object assigned, but arguments only exist while the method is being
called (or ACTIVE, meaning: they are part of the call chain).


Methods of objects and classes always have an implicit parameter, that
is bound to the object or class the method was called on. In the case of
classmethods, it will be a class. In the case of objects, it will be an
object. (In case of static methods, there is no implicit parameter.)

Apart from being an implicit parameter, there is nothing special about
the first parameter of a method.


> does the self. prefix modify this scope?
It should be clear now, that in this case:

def pressure_calc(self):

the name "self" is a formal parameter of the "pressure_calc" method, because it 
is in the formal parameter list. When this method gets called, the name "self" 
is assigned to the object the method was called on. Because the name "self" is 
a parameter, it will be a local name of the method, and it will be accessible 
from inside that method only.


-- 
https://mail.python.org/mailman/listinfo/python-list