Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Need help to pass self.count to other classes.

1 view
Skip to first unread message

Bill

unread,
Jan 6, 2010, 5:11:49 AM1/6/10
to
After a year with Python 2.5 on my Windows box, I still have trouble
understanding classes.

Below, see the batch file and the configuration script for
my Python interactive prompt.

The widths of the secondary prompts increase when the self.count of
SysPrompt1 exceeds 99.

I am using a global variable "zxc" to share self.count, which is not
Pythonic.

How can I pass in self.count without a global?
I did RTFM, aka Google, but to no avail.

echo py.bat
set PYTHONSTARTUP=c:\scripts\startup.py
python
^Z

# startup.py
# inspired by:
# http://www.doughellmann.com/PyMOTW/sys/interpreter.html

import sys

class SysPrompt1(object):
def __init__(self):
self.count = 0
def __str__(self):
self.count += 1
global zxc
zxc = self.count
return '[%2d]> ' % self.count

class SysPrompt2(object):
def __str__(self):
global zxc
if zxc > 99: return '...... '
else: return '..... '

class DisplayHook(object):
def __call__(self, value):
if value is None: return
global zxc
if zxc > 99: print '[ out]', value, '\n'
else: print '[out]', value, '\n'

class ExceptHook(object):
def __call__(self, type, value, trace):
global zxc
if zxc > 99: print '[ err]', value, '\n'
else: print '[err]', value, '\n'

sys.ps1 = SysPrompt1()
sys.ps2 = SysPrompt2()
sys.displayhook = DisplayHook()
sys.excepthook = ExceptHook()

Francesco Bochicchio

unread,
Jan 6, 2010, 5:43:06 AM1/6/10
to
On 6 Gen, 11:11, Bill <bsag...@gmail.com> wrote:
> After a year with Python 2.5 on my Windows box, I still have trouble
> understanding classes.
>
> Below, see the batch file and the configuration script for
> my Python interactive prompt.
>
> The widths of the secondary prompts increase when  the self.count of
> SysPrompt1 exceeds 99.
>
> I am using a global variable "zxc" to share self.count, which is not
> Pythonic.
>
> How can I pass in self.count without a global?
> I did RTFM, aka Google, but to no avail.
>
> echo py.bat
> set PYTHONSTARTUP=c:\scripts\startup.py
> python
> ^Z
>
> # startup.py
> # inspired by:
> #http://www.doughellmann.com/PyMOTW/sys/interpreter.html

First of all, you shouldn't do OOP if you don't feel it. Python,
unlike Java and like C++, supports also procedural programming, so you
can write your scripts without writing classes (but still using
objects, since all in python is an object).
If you have classes with no data and a single __call_ method, then
they are no classes, they are functions (or methods) in disguise.
So, one solution could be to use plain functions and use global as you
already do. 'global' is pythonic if you are not doing OOP, although I
don't like it.

If you want to stick to OOP, then I suggest to have a make
display_hook and except_hook methods of your class SysPrompt1; This
way all your code can access to self.count without needing globals.
As for your class SysPrompt2, I don't understand enough your code to
know what you are trying to do. maybe make it a sunclass of
SysPrompt1 ?

HTH

Ciao
----
FB

Bruno Desthuilliers

unread,
Jan 6, 2010, 8:13:25 AM1/6/10
to
Bill a �crit :

> After a year with Python 2.5 on my Windows box, I still have trouble
> understanding classes.
>
> Below, see the batch file and the configuration script for
> my Python interactive prompt.
>
> The widths of the secondary prompts increase when the self.count of
> SysPrompt1 exceeds 99.
>
> I am using a global variable "zxc" to share self.count, which is not
> Pythonic.

It's not "unpythonic" - but it's not good OO style neither !-)

> How can I pass in self.count without a global?

(snip)

> sys.ps1 = SysPrompt1()
> sys.ps2 = SysPrompt2()
> sys.displayhook = DisplayHook()
> sys.excepthook = ExceptHook()
>

hint #1: a bound method is also a callable.
hint #2: an object can be an attribute of another object.


Possible OO solution:

class Counter(object):
def __init__(self):
self._count = 0
def inc(self):
self._count += 1
value = property(fget=lambda s: s._count)

class Prompt1(object):
def __init__(self, counter):
self._counter = counter
def _str_(self):
self._counter.inc()
return '[%2d]> ' % self._counter.value

class Prompt2(object):
def __init__(self, counter):
self._counter = counter
def _str_(self):
if self._counter.value > 99: # XXX magic number


return '...... '
else:
return '..... '

class MySysHookHandler(object):
def __init__(self):
self._counter = Counter()
self.ps1 = Prompt1(self._counter)
self.ps2 = Prompt2(self._counter)

def displayhook(self, value):


if value is None:
return

if self._counter.value > 99: # XXX magic number


print '[ out]', value, '\n'
else:
print '[out]', value, '\n'

def excepthook(self, type, value, trace):
if self._counter.value > 99: # XXX magic number


print '[ err]', value, '\n'
else:
print '[err]', value, '\n'


handler = MySysHook()
sys.ps1 = handler.ps1
sys.ps2 = handler.ps2
sys.displayhook = handler.displayhook
sys.excepthook = handler.excepthook

HTH

Steve Holden

unread,
Jan 6, 2010, 8:56:23 AM1/6/10
to pytho...@python.org
As Francesco points out, OO programming isn't *mandatory* in Python.

However, if you used a single class instead of multiples then you could
use an instance variable for zxc, and have each of the functions be
bound methods (i.e. methods of the instance, not the class).

This is untested code (some days I don't seem to write any other kind
...) but it should give you the flavor:

class kbInterface(object):
def __init__(self):
self.zxc = 0
def prompt1(self):
self.count += 1
return "[%d]> "
def prompt2(self):
l = len(str(self.count))+1
return "%s " % "."*l
def dhook(self, value):
print "[%d out]" % self.count
def ehook(self, type, value, trace):
print "[%d err]\n" % value

kbi = kbInterface()
sys.ps1 = kbi.prompt1
sys.ps2 = kbi.prompt2
sys.displayhook = kbi.dhook
sys.excepthook = kbi.ehook

Do you get the idea? Now the count is shared between all the methods,
and it's available in the instance's namespace.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
PyCon is coming! Atlanta, Feb 2010 http://us.pycon.org/
Holden Web LLC http://www.holdenweb.com/
UPCOMING EVENTS: http://holdenweb.eventbrite.com/

Bruno Desthuilliers

unread,
Jan 6, 2010, 10:41:36 AM1/6/10
to
Steve Holden a �crit :
(snip)
> This is untested code

indeed !-)

> class kbInterface(object):
> def __init__(self):
> self.zxc = 0
> def prompt1(self):
> self.count += 1

Ahem...

(snip)


Steve Holden

unread,
Jan 6, 2010, 11:42:21 AM1/6/10
to pytho...@python.org
Caveat emptor ... this code is worth what you paid for it :)

Steven D'Aprano

unread,
Jan 7, 2010, 11:56:18 PM1/7/10
to
On Wed, 06 Jan 2010 08:56:23 -0500, Steve Holden wrote:

> This is untested code (some days I don't seem to write any other kind
> ...) but it should give you the flavor:
>
> class kbInterface(object):
> def __init__(self):
> self.zxc = 0
> def prompt1(self):
> self.count += 1
> return "[%d]> "
> def prompt2(self):
> l = len(str(self.count))+1
> return "%s " % "."*l
> def dhook(self, value):
> print "[%d out]" % self.count
> def ehook(self, type, value, trace):
> print "[%d err]\n" % value
>
> kbi = kbInterface()
> sys.ps1 = kbi.prompt1
> sys.ps2 = kbi.prompt2
> sys.displayhook = kbi.dhook
> sys.excepthook = kbi.ehook


Unfortunately this won't do what you expect, because sys.ps1 and ps2
should be either strings, or objects with a __str__ method. They aren't
called to generate the prompt.

(After fixing the typo with self.count vs self.zxc)


>>> kbi = kbInterface()
>>> sys.ps1 = kbi.prompt1

<bound method kbInterface.prompt1 of <__main__.kbInterface object at
0xb7cbd52c>>print "Hello"
Hello
<bound method kbInterface.prompt1 of <__main__.kbInterface object at
0xb7cbd52c>>

--
Steven

Steve Holden

unread,
Jan 8, 2010, 8:58:50 AM1/8/10
to pytho...@python.org
Steven D'Aprano wrote:
[... points out my misapprehension ...]

>
>>>> kbi = kbInterface()
>>>> sys.ps1 = kbi.prompt1
> <bound method kbInterface.prompt1 of <__main__.kbInterface object at
> 0xb7cbd52c>>print "Hello"
> Hello
> <bound method kbInterface.prompt1 of <__main__.kbInterface object at
> 0xb7cbd52c>>
>
Right, this is expert mode ...

Peter Otten

unread,
Jan 8, 2010, 1:10:37 PM1/8/10
to
Steve Holden wrote:

> Steven D'Aprano wrote:
> [... points out my misapprehension ...]
>>
>>>>> kbi = kbInterface()
>>>>> sys.ps1 = kbi.prompt1
>> <bound method kbInterface.prompt1 of <__main__.kbInterface object at
>> 0xb7cbd52c>>print "Hello"
>> Hello
>> <bound method kbInterface.prompt1 of <__main__.kbInterface object at
>> 0xb7cbd52c>>
>>
> Right, this is expert mode ...

Here's a way to turn expert mode into something less advanced:

>>> import sys
>>> def expert_mode():
... return "for newbies ;) "
...
>>> sys.ps1 = expert_mode
<function expert_mode at 0x7f498b9735f0>class Str:
... def __init__(self, f): self.f = f
... def __str__(self): return self.f()
...
<function expert_mode at 0x7f498b9735f0>sys.ps1 = Str(expert_mode)
for newbies ;)

Peter

Lie Ryan

unread,
Jan 9, 2010, 1:14:31 AM1/9/10
to
On 1/8/2010 3:56 PM, Steven D'Aprano wrote:
> Unfortunately this won't do what you expect, because sys.ps1 and ps2
> should be either strings, or objects with a __str__ method. They aren't
> called to generate the prompt.

but their __str__ does get called to generate the prompt.

import sys

class kbInterfaceHelper(object):
def __init__(self, str_func):
self.str_func = str_func
def __str__(self):
return self.str_func()

class kbInterface(object):
def __init__(self):
self.count = 0


def prompt1(self):
self.count += 1

return "[%d]> " % self.count


def prompt2(self):
l = len(str(self.count))+1
return "%s " % "."*l
def dhook(self, value):
print "[%d out]" % self.count
def ehook(self, type, value, trace):
print "[%d err]\n" % value

kbi = kbInterface()
sys.ps1 = kbInterfaceHelper(kbi.prompt1)
sys.ps2 = kbInterfaceHelper(kbi.prompt2)

0 new messages