Need help to pass self.count to other classes.

B

Bill

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()
 
F

Francesco Bochicchio

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()

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
 
B

Bruno Desthuilliers

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
 
S

Steve Holden

Bill said:
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()
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
 
S

Steven D'Aprano

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)

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

Steve Holden

Steven D'Aprano wrote:
[... points out my misapprehension ...]
<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 ...

regards
Steve
 
P

Peter Otten

Steve said:
Steven D'Aprano wrote:
[... points out my misapprehension ...]
<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:
.... return "for newbies ;) "
....<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
 
L

Lie Ryan

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)
sys.displayhook = kbi.dhook
sys.excepthook = kbi.ehook
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,152
Members
46,697
Latest member
AugustNabo

Latest Threads

Top