Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > (newbie) Is there a way to prevent "name redundancy" in OOP ?

Reply
Thread Tools

(newbie) Is there a way to prevent "name redundancy" in OOP ?

 
 
Stef Mientki
Guest
Posts: n/a
 
      01-05-2007
Not sure I wrote the subject line correct,
but the examples might explain if not clear


*** first attempt ***
class pin:
def __init__ (self):
self.Name = 'Unknown Pin'

aap = pin() # create an instance
aap.Name = 'aap' # set it's name
print aap.Name # print it's name
# but why should I set it's name ??
print 'aap' # I can just as well print a constant string !!
# (ok there will be an extra check)


*** second attempt ***
class pin2:
def __init__ (self, naam):
self.Name = naam

aap2 = pin2('aap2') # seems completely redundant to me.
print aap2.Name
print 'aap2'


Can this be achieved without redundancy ?

thanks,
Stef Mientki
 
Reply With Quote
 
 
 
 
Laszlo Nagy
Guest
Posts: n/a
 
      01-05-2007
Stef Mientki wrote:
> Not sure I wrote the subject line correct,
> but the examples might explain if not clear
>
>
> *** first attempt ***
> class pin:
> def __init__ (self):
> self.Name = 'Unknown Pin'
>
> aap = pin() # create an instance
> aap.Name = 'aap' # set it's name
> print aap.Name # print it's name
>
> # but why should I set it's name ??
> print 'aap' # I can just as well print a constant string !!
> # (ok there will be an extra check)
>

If you are trying to determine the name of your object, then you do not
know what 'name' and 'object' means in Python. In this case, I recommend
you this:

http://effbot.org/zone/python-objects.htm

In particular, pay attention to that objects can have zero or more names.

This is how you can create three unnamed objects:

L = [pin(),pin(),pin(),]

This is how you can bind three names to the same object:

p1 = p2 = p3 = pin()

Maybe I did not understand you question.

Laszlo

 
Reply With Quote
 
 
 
 
Fuzzyman
Guest
Posts: n/a
 
      01-05-2007

Stef Mientki wrote:
> Not sure I wrote the subject line correct,
> but the examples might explain if not clear
>
>
> *** first attempt ***
> class pin:
> def __init__ (self):
> self.Name = 'Unknown Pin'
>
> aap = pin() # create an instance
> aap.Name = 'aap' # set it's name
> print aap.Name # print it's name
> # but why should I set it's name ??
> print 'aap' # I can just as well print a constant string !!
> # (ok there will be an extra check)
>
>
> *** second attempt ***
> class pin2:
> def __init__ (self, naam):
> self.Name = naam
>
> aap2 = pin2('aap2') # seems completely redundant to me.
> print aap2.Name
> print 'aap2'
>
>
> Can this be achieved without redundancy ?
>


Uhm.. if your code can work with a constant then creating an object to
hold it as an attribute is redundant.

If on the other hand you want an object to hold several attributes, and
methods for working with them, and then want to pass these objects
around your code with a single reference - then maybe an object is the
best way.

If you don't need custom classes then don't use them...

Fuzzyman
http://www.voidspace.org.uk/python/articles.shtml

> thanks,
> Stef Mientki


 
Reply With Quote
 
Jorge Vargas
Guest
Posts: n/a
 
      01-05-2007
On 1/5/07, Stef Mientki <(E-Mail Removed)> wrote:

if I undestand correctly this is what you want

>>> class pin3:

.... def __init__(self,name):
.... self.Name = name
.... def __str__(self):
.... return self.Name
....
>>> pin3()

Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: __init__() takes exactly 2 arguments (1 given)
>>> pin3('aaa')

<__main__.pin3 instance at 0xb7dc948c>
>>> print pin3('aaa')

aaa
 
Reply With Quote
 
Carl Banks
Guest
Posts: n/a
 
      01-05-2007

Stef Mientki wrote:
> Not sure I wrote the subject line correct,
> but the examples might explain if not clear
>
>
> *** first attempt ***
> class pin:
> def __init__ (self):
> self.Name = 'Unknown Pin'
>
> aap = pin() # create an instance
> aap.Name = 'aap' # set it's name
> print aap.Name # print it's name
> # but why should I set it's name ??
> print 'aap' # I can just as well print a constant string !!
> # (ok there will be an extra check)
>
>
> *** second attempt ***
> class pin2:
> def __init__ (self, naam):
> self.Name = naam
>
> aap2 = pin2('aap2') # seems completely redundant to me.
> print aap2.Name
> print 'aap2'
>
>
> Can this be achieved without redundancy ?


No. Simply not possible in Python.

You should consider whether there is another opportunity to eliminate
the redundancy. For instance, it looks like these pin definitions
might end up in a dictionary of some sort (I don't know your use case).
You could automatically generate the keys from the names like this:

_pindefs = (
pin("aap"),
pin("wap"),
pin("dcr"),
...
)
pins = {}
for pin in _pindefs:
pins[pin.Name] = pin

Then you access pins["aap"]. The reason I suspect the pins will end up
in a dictionary is that, in many real applications, the pin name would
often be specified in the input. (This is very often the case whenever
people want to know the symbol an object is bound to, for any
application.)


Carl Banks

 
Reply With Quote
 
Martin Miller
Guest
Posts: n/a
 
      01-06-2007
Stef Mientki wrote:
> Not sure I wrote the subject line correct,
> but the examples might explain if not clear
>
>
> *** first attempt ***
> class pin:
> def __init__ (self):
> self.Name = 'Unknown Pin'
>
> aap = pin() # create an instance
> aap.Name = 'aap' # set it's name
> print aap.Name # print it's name
> # but why should I set it's name ??
> print 'aap' # I can just as well print a constant string !!
> # (ok there will be an extra check)


While I agree that it's likely you're confusing Python objects and
names, Python *is* an interpreted language and therefore very flexible.
Here's a snippet showing one way to remove the 'redundancy'. (Be
forewarned that doing things like this is highly distasteful to some
people.)

### non-redundant example ###
import sys

class Pin:
def __init__(self, name, namespace=None):
self.name = name
if namespace == None:
# default to caller's globals
namespace = sys._getframe(1).f_globals
namespace[name] = self

Pin('aap') # create a Pin object named 'aap'
Pin('aap2') # create a Pin object named 'aap2'
print aap.name
print aap2.name

-Martin

 
Reply With Quote
 
Carl Banks
Guest
Posts: n/a
 
      01-06-2007

Martin Miller wrote:
> ### non-redundant example ###
> import sys
>
> class Pin:
> def __init__(self, name, namespace=None):
> self.name = name
> if namespace == None:
> # default to caller's globals
> namespace = sys._getframe(1).f_globals
> namespace[name] = self
>
> Pin('aap') # create a Pin object named 'aap'
> Pin('aap2') # create a Pin object named 'aap2'
> print aap.name
> print aap2.name


The problem with this is that it only works for global namespaces,
while failing silently and subtly if used in a local namespace:

def fun():
Pin('aap')
aap1 = aap
fun2()
aap2 = aap
print aap1 is aap2

def fun2():
Pin('aap')

If it's your deliberate intention to do it with the global namespace,
you might as well just use globals() and do it explicitly, rather than
mucking around with Python frame internals. (And it doesn't make the
class unusable for more straightforward uses.)

for _name in ('aap','dcr'):
globals()[_name] = Pin(_name)
del _name


Carl Banks

 
Reply With Quote
 
Steven Bethard
Guest
Posts: n/a
 
      01-06-2007
Stef Mientki wrote:
> Not sure I wrote the subject line correct,
> but the examples might explain if not clear

[snip]
> class pin2:
> def __init__ (self, naam):
> self.Name = naam
>
> aap2 = pin2('aap2') # seems completely redundant to me.
> print aap2.Name


You can use class statements to create your instances with some
metaclass trickery. Unlike normal assignments, class statements get
access to the name being assigned. So you could write your class like::

>>> class pin(object):

... def __init__(self, name):
... self.name = name
... @classmethod
... def from_class_block(cls, name, bases, block_dict):
... return cls(name)
...

And then use class statements to create instances of the ``pin`` class::

>>> class aap:

... __metaclass__ = pin.from_class_block
...
>>> print aap.name

aap
>>> type(aap)

<class '__main__.pin'>

Of course, using class statements to create *instances* of a class is
confusing. And it's more verbose than simply repeating the name when you
call the constructor. But at least it avoids the redundancy.

STeVe
 
Reply With Quote
 
Stef Mientki
Guest
Posts: n/a
 
      01-06-2007

Steven Bethard wrote:
> Stef Mientki wrote:
>> Not sure I wrote the subject line correct,
>> but the examples might explain if not clear

> [snip]
>> class pin2:
>> def __init__ (self, naam):
>> self.Name = naam
>>
>> aap2 = pin2('aap2') # seems completely redundant to me.
>> print aap2.Name

>
> You can use class statements to create your instances with some
> metaclass trickery. Unlike normal assignments, class statements get
> access to the name being assigned. So you could write your class like::


thank you all guys,
this gives me a lot to study,
for the moment I'm satisfied with the fact that it "is possible".

cheers,
Stef Mientki
 
Reply With Quote
 
Martin Miller
Guest
Posts: n/a
 
      01-07-2007
Carl Banks wrote:

> Martin Miller wrote:
> > ### non-redundant example ###
> > import sys
> >
> > class Pin:
> > def __init__(self, name, namespace=None):
> > self.name = name
> > if namespace == None:
> > # default to caller's globals
> > namespace = sys._getframe(1).f_globals
> > namespace[name] = self
> >
> > Pin('aap') # create a Pin object named 'aap'
> > Pin('aap2') # create a Pin object named 'aap2'
> > print aap.name
> > print aap2.name

>
> The problem with this is that it only works for global namespaces,
> while failing silently and subtly if used in a local namespace:


Oh, contrair. It would work fine with local namespaces simply by
overriding the default value of the optional 'namepace' parameter (see
below).

> def fun():
> Pin('aap')
> aap1 = aap
> fun2()
> aap2 = aap
> print aap1 is aap2
>
> def fun2():
> Pin('aap')
>
> If it's your deliberate intention to do it with the global namespace,
> you might as well just use globals() and do it explicitly, rather than
> mucking around with Python frame internals. (And it doesn't make the
> class unusable for more straightforward uses.)


You could be more explicit by just passing 'globals()' as a second
parameter to the __init__ constructor (which is unnecessary, since
that's effectively the default).

It's not clear to me how the example provided shows the technique
"failing silently and subtly if used in a local namespace" because what
happens is exactly what I would expect if the constructor is called
twice with the same string and defaulted namespace -- namely create
another object and make the existing name refer to it. If one didn't
want the call to Pin in fun2 to do this, just change fun2 to this:

def fun2():
Pin('aap', locals())

This way the "print aap1 is aap2" statement in fun() would output
"true" since the nested call to Pin would now (explicitly) cause the
name of the new object to be put into fun2's local namespace leaving
the global one created by the call in fun() alone.

Obviously, this was not an objection I anticipated. An important one I
would think is the fact that the current documentation says that
f_globals is a special *read-only* attribute of a frame object implying
that it shouldn't be changed (even though doing so 'works' as my
example illustrates).

I think other valid arguments against this practice might include
whether it's an example of good OOP, or a good programming practice at
all, since it involves possibly subtle side-effects, the use of global
variables, and/or is 'unpythonic'.

Certainly the approach is not without caveats. Despite them, I believe
it can be useful in some contexts, as long as what is going on is
clearly understood. The point of my reply to the OP was mainly just to
illustrate the power and flexibility of Python to the newbie. I guess
to that I should have also added that it gives you "enough rope to
shoot yourself" as Allen Holub said regarding C++.

Cheers,
-Martin

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Parsing Binary Structures; Is there a better way / What is your way? Paul Rubin Python 5 08-06-2009 08:06 AM
Is there a way to tie down a file to a computer? Prevent data theft? RakperBanengen@yahoo.com Computer Security 4 06-03-2009 04:50 PM
PERL OOP newbie question: What is the best way to handle array data? lovellj@mcmaster.ca Perl Misc 4 05-04-2007 04:53 AM
Is there a way with Linux x86 to report a way the current stack trace for a thread? kevin.hall@motioneng.com C++ 4 10-20-2005 09:43 PM
Is there a way to prevent files from being dragged-and-dropped from a CD? Julia Briggs Computer Security 19 09-20-2005 02:43 AM



Advertisments