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

Search Discussions

  • Francesco Bochicchio at Jan 6, 2010 at 10:43 am

    On 6 Gen, 11:11, Bill 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

    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
    ----
    FB
  • Bruno Desthuilliers at Jan 6, 2010 at 1:13 pm

    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 at Jan 6, 2010 at 1:56 pm

    Bill 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

    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
    --
    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 at Jan 6, 2010 at 3:41 pm
    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 at Jan 6, 2010 at 4:42 pm

    Bruno Desthuilliers wrote:
    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)
    Caveat emptor ... this code is worth what you paid for it :)

    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/
  • Steven D'Aprano at Jan 8, 2010 at 4:56 am

    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 at Jan 8, 2010 at 1:58 pm
    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 ...

    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/
  • Peter Otten at Jan 8, 2010 at 6:10 pm

    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 at Jan 9, 2010 at 6:14 am

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

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedJan 6, '10 at 10:11a
activeJan 9, '10 at 6:14a
posts10
users7
websitepython.org

People

Translate

site design / logo © 2023 Grokbase