[Tutor] newbie-class differs from function?

Bob Gailer ramrom@earthling.net
Tue Mar 11 13:01:09 2003


--=======37B9FA1=======
Content-Type: text/plain; x-avg-checked=avg-ok-56465677; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 8bit

At 10:06 AM 3/11/2003 -0400, D2 wrote:
>[snip]

The "straightforward answer" (written last but appearing first): to get the 
__init__ (or any other) method's parameters:

class c:
   def __init__(self,a,b):pass
c.__init__.im_func.func_code.co_varnames # returns ('self', 'a', 'b')

(CHEERS to PythonWin autocompletion for getting this sequence quickly w/o 
having to look it up.)

>when you want to create an instance of a class you must use a function 
>with parameters to set the instance properties.

Here are the alternatives, including ways that don't require functions:

direct assignment:

class a:pass # class with no methods or properties
b = a() # instance
b.newproperty = 313 # give the instance a property and set its value

My approach for setting properties via a method is:

class a:
   def setprop(self, name, value): # setprop is an arbitrary name
     setattr(self, name, value) # setattr is a built-in function

b = a() # instance
b.setprop('newproperty', 313) # give the instance a property and set its value

direct assignment and setattr both in effect do the following:

b.__dict__['newproperty'] = 313

since instance properties are really dictionary entries.

There is also the 'magic' method __setattr__(self, name, value). If this 
method is defined in the class, then direct assignment and setattr each call:
b.__setattr__(self, name, value). In this case you have a place where you 
can make tests and perform actions on name and value. In order to actually 
set the property you MUST use self.__dict__[name] = value, since direct 
assignment and setattr used within __setattr__ will recursively call 
__setattr__.

class a:
   def __setattr__(self, name, value) :
     # process name, value?
     self.__dict__[name] = value

b = a() # instance
b.newproperty = 313 # calls __setattr__(b, 'newproperty', 313)

In all of these cases except __dict__ assignment, one must ensure that name 
is an "identifier" e.g. _A-Za-z followed by _A-Za-z0-9. When assigning 
directly to the dictionary, the key can be any hashable object. Of course, 
if it is not an identifier (e.g 5), then it can't be referenced by 
b.propertyname. This can also cause problems and/or anomalies in IDEs that 
offer autocompletion. For example, in PythonWin, given that b is a class 
instance:

 >>> b.__dict__[(4, 5)] = 5
 >>> b.
at which point auto complete offers:
(4,
5)
which is not correct, and not usable!

>What i want is to verify what parameters are used to construct an instance 
>of a class, and how, given the class and assuming that i only know the 
>name of the class and the initial constructor.
>I want to do that before creating an instance, to pass the description to 
>a computer program which will provide the necessary data to create an instance.
>Let's take the example of human being.
>I think i don't need to explain the __init__ method of the HumanBeing 
>class. Do i ? :). Knowing it, i can find the parameters to pass to build 
>an instance of HumanBeing class.
>But what if i want to set the HumanBeing.knowledge property ? What are the 
>methods ? So i'll have to search in the source files. That's what my 
>example was not saying but what i want to do with my small application.

Given what I've said above I think you can let go of the idea of "knowing" 
what parameters are "required", and use some other easier way to manage 
associations between different kinds of input and class properties, e.g. a 
dictionary keyed by the input type and having tuples of parameter names as 
values.

OTOH if you REALLY want to associate the parameter names with the class, do 
this:

class c:
   a=0
   b=0

c.__dict__ # returns {'a': 0, '__module__': '__main__', 'b': 0, '__doc__': 
None}

You'll have to ignore the __module__, __main__ and __doc__ entries; the 
rest are your "parameters". You'd set them using any of the above mentioned 
methods, or all at once by defining a method in the class to set them all 
at once:

Bob Gailer
mailto:ramrom@earthling.net
303 442 2625

--=======37B9FA1=======
Content-Type: text/plain; charset=us-ascii; x-avg=cert; x-avg-checked=avg-ok-56465677
Content-Disposition: inline


---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.459 / Virus Database: 258 - Release Date: 2/25/2003

--=======37B9FA1=======--