Asymmetry in globals __getitem__/__setitem__

2014-06-12 Thread Robert Lehmann
Hi all,

I have noticed there is a slight asymmetry in the way the interpreter
(v3.3.5, reproduced also in v3.5.x) loads and stores globals.  While
loading globals from a custom mapping triggers __getitem__ just fine,
writing seems to silently ignore __setitem__.

class Namespace(dict):
def __getitem__(self, key):
print("getitem", key)
def __setitem__(self, key, value):
print("setitem", key, value)

def fun():
global x, y
x  # should call globals.__getitem__
y = 1  # should call globals.__setitem__

exec(fun.__code__, Namespace())
# => getitem x

I would have expected "setitem y 1" to show up as well, but to no avail.
 Am I doing something wrong?  Is this on purpose?

Cheers,
Robert

PS.  I found a 3.3.x commit (e3ab8aa
) which fixed the
LOAD_GLOBAL opcode to support other types than dict, but STORE_GLOBAL seems
to use bare PyDict_SetItem instead of dispatching to PyObject_SetItem.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: how to overload operator "< <" (a < x < b)?

2009-08-07 Thread Robert Lehmann
On Fri, 07 Aug 2009 08:50:52 -0400, Benjamin Kaplan wrote:

> On Fri, Aug 7, 2009 at 8:00 AM, dmitrey
> wrote:
>> hi all,
>> is it possible to overload operator "<  <"? (And other like this one,
>> eg "<=  <=", ">  >", ">=  >=")
>> Any URL/example?
>> Thank you in advance, D.
> 
> That isn't an operator at all. Python does not support compound
> comparisons like that. You have to do "a > b and b > c".

Python actually allows you to chain comparison operators, automatically 
unpacking ``a > b > c`` to ``a > b and b > c``::

>>> class C(object):
...   def __lt__(self, other):
... print self, "LESS-THAN", other
... return True
... 
>>> a = C(); b = C(); x = C()
>>> a < x < b
<__main__.C object...> LESS-THAN <__main__.C object...>
<__main__.C object...> LESS-THAN <__main__.C object...>
True

>>> x = 42
>>> 40 < x < 50 # between 40 and 50
True
>>> 50 < x < 60 # between 50 and 60
False
>>> 1 == True < 2 == 2.0 < 3 < 4 != 5 > 0 # yikes, unreadable! but legal.
True
>>> # same as: (1 == True) and (True < 2) and (2 == 2.0) ...

HTH,

-- 
Robert "Stargaming" Lehmann

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: no sign() function ?

2008-12-22 Thread Robert Lehmann
On Mon, 22 Dec 2008 12:31:44 +0100, Pierre-Alain Dorange wrote:

>> > I don't find any sign(x) function in the math library (return the
>> > sign of the value).
>> > I've read that math module is a wrapper to C math lib and that C math
>> > lib has not sign(), so...
[snip]
> As my need is for a game and that i do not have IEEE real concern, i
> would simply using my simple function (but not as accurate) :
> 
> def sign(x):
> if x==0.0:
> return 0.0
> elif x>0.0:
> return 1.0
> else:
> return -1.0

I found this snippet to be quite succinct (even though being smart 
*might* be wrong in programming)::

sign = lambda x:+(x > 0) or -(x < 0)

HTH,

-- 
Robert "Stargaming" Lehmann
--
http://mail.python.org/mailman/listinfo/python-list


Re: List Problem

2008-12-09 Thread Robert Lehmann
On Tue, 09 Dec 2008 21:40:08 -0800, dongzhi wrote:

> I have one problem for List. Like that:
> 
> format='just "a" ""little"" test'
> part = format.split('"')
> print part
> 
> the result is : ['just ', 'a', ' ', '', 'little', '', ' test']
> 
> the list part have 7 element.
> 
> If I execute part[1], I have got  'a'. If I execute part[2], I have got
> ' '. But, if I execute part[1::2], I have got ['a', '', '']. I don't
> know why. Please tell me why.

You're slicing your list with the arguments "start at 1, stop at the end, 
using a step size of 2." It's basically the same as ``part[1], part[1+2], 
part[1+2+2], ...``. Perhaps you wanted to do ``part[1:3]`` (meaning 
"start at 1, stop before 3").

See the Python Reference for details.
http://docs.python.org/library/stdtypes.html#sequence-types-str-unicode-
list-tuple-buffer-xrange
http://docs.python.org/reference/expressions.html#id8

HTH,

-- 
Robert "Stargaming" Lehmann
--
http://mail.python.org/mailman/listinfo/python-list


Re: multiple breaks

2008-11-15 Thread Robert Lehmann
On Thu, 13 Nov 2008 02:16:32 -0800, Chris Rebert wrote:

> On Thu, Nov 13, 2008 at 2:07 AM, TP <[EMAIL PROTECTED]>
> wrote:
>>
>> In the following example, is this possible to affect the two iterators
>> to escape the two loops once one "j" has been printed:
>>
> Non-exception alternative:
> 
> done = False
> for i in range(5):
>for j in range(i):
>   print j
> done = True
> break
> if done:
> break

Another alternative is explicitly jumping in the outer loop::

  for i in range(5): # use xrange for larger ranges
  for j in range(i):
  print j
  break
  else:
  continue # applies already to the outer loop
  break

HTH,

-- 
Robert "Stargaming" Lehmann
--
http://mail.python.org/mailman/listinfo/python-list


Re: My first Python program -- a lexer

2008-11-10 Thread Robert Lehmann
On Sun, 09 Nov 2008 15:53:01 +0100, Thomas Mlynarczyk wrote:

> Arnaud Delobelle schrieb:
> 
>> Adding to John's comments, I wouldn't have source as a member of the
>> Lexer object but as an argument of the tokenise() method (which I would
>> make public).  The tokenise method would return what you currently call
>> self.result.  So it would be used like this.
> 
> mylexer = Lexer(tokens)
> mylexer.tokenise(source)
> mylexer.tokenise(another_source)
> 
> At a later stage, I intend to have the source tokenised not all at once,
> but token by token, "just in time" when the parser (yet to be written)
> accesses the next token:

You don't have to introduce a `next` method to your Lexer class. You 
could just transform your `tokenize` method into a generator by replacing 
``self.result.append`` with `yield`. It gives you the just in time part 
for free while not picking your algorithm into tiny unrelated pieces.

>  token = mylexer.next( 'FOO_TOKEN' )
>  if not token: raise Exception( 'FOO token expected.' ) # continue
>  doing something useful with token
> 
> Where next() would return the next token (and advance an internal
> pointer) *if* it is a FOO_TOKEN, otherwise it would return False. This
> way, the total number of regex matchings would be reduced: Only that
> which is expected is "tried out".

Python generators recently (2.5) grew a `send` method. You could use 
`next` for unconditional tokenization and ``mytokenizer.send("expected 
token")`` whenever you expect a special token.

See http://www.python.org/dev/peps/pep-0342/ for details.

HTH,

-- 
Robert "Stargaming" Lehmann
--
http://mail.python.org/mailman/listinfo/python-list


Re: Snippets management

2008-11-06 Thread Robert Lehmann
On Thu, 06 Nov 2008 05:23:25 -0600, Edwin wrote:
[snip]
> As I'm learning Python sometimes I look for different approaches to the
> same problem so I use Git branches in order to save every try. It's
> just that I'm looking for a 'global' place in my system where I can
> save code ideas and useful snippets not particular to any project.
> Quick access could be useful for some copy/paste operations...
> I don't know.
> 
> How would you set this up? A git folder 'snippets' maybe?
> 
> Thanks for your ideas.

I don't think there is a one-size-fits-all solution.

Setting up a 'snippets' repository sounds good if you just want to be 
able to look back at what you've done and/or have a place to stash away 
quick tests. I have set up a 'sandbox' folder (unrevisioned) and put 
together a few shell aliases for easier access and it works pretty well. 
I almost never look back at that code though.

If you develop a lot of small scripts you think you'll reuse in your 
daily routine, you should add a dedicated 'bin' directory and add it to 
your PATH.

I've also seen people put together libraries of "personal helpers", say, 
libedwin, but I don't think such mashups offer any particular semantic 
gain. They will just bloat over time and be vastly unused in most 
projects.

So, I don't really know what you should do. I'd go for a throw away 
location for quick tests; *real* libraries/programs where reasonable. If 
you need a particular algorithm and know you've used it in project XY, 
just go back to this project and copy it. No big deal. If it's a 
generally applicable algorithm, extracting a library might be a good idea 
then.

Just one last hint: Don't be overly shy in creating new Git repositories. 
They're pretty cheap and a shared history for *deeply unrelated projects* 
is seldom sensible (IMO). GitHub doesn't restrict you in your number of 
public repositories so that's no deal breaker either. :-)

Snippet'ly yours,

-- 
Robert "Stargaming" Lehmann
--
http://mail.python.org/mailman/listinfo/python-list


Re: Snippets management

2008-11-06 Thread Robert Lehmann
On Wed, 05 Nov 2008 19:55:51 -0600, Edwin wrote:

> Hi there,
> 
> I've been looking for a snippet manager and found PySnippet but it
> requires PyGTK. Do you know any other option that doesn't need much?
[snip]

If you're looking for a snippet manager for actually *using* it (not 
educational purposes or something), I'd recommend your favorite editor 
and the version control system of your choice. I found DVCSes to be 
rather nice for local ad-hoc repositories (particulary Git_). If you'd 
like to modify your snippet system you could take a look at Mercurial or 
Bazaar, both being written in Python.

HTH,

.. _Git: http://git.or.cz/

-- 
Robert "Stargaming" Lehmann
--
http://mail.python.org/mailman/listinfo/python-list


Re: contextlib.nested()

2008-11-06 Thread Robert Lehmann
On Thu, 06 Nov 2008 01:02:34 -0800, brasse wrote:
> Hello!
> 
> I have been running in to some problems when using contextlib.nested().
> My problem arises when using code similar to this:
> 
> from __future__ import with_statement
> 
> from contextlib import nested
> 
> class Foo(object):
> 
> def __init__(self, tag, fail=False):
> print 'ctor', tag
> self.tag = tag
> if fail:
> raise Exception()
> 
> def __enter__(self):
> print '__enter__', self.tag
> return self
> 
> def __exit__(self, *args):
> print '__exit__', self.tag
> 
> with nested(Foo('a'), Foo('b', True)) as (a, b):
> print a.tag
> print b.tag
> 
> Here the construction of b fails which in turn means that the
> contextmanager fails to be created leaving me a constructed object (a)
> that needs to be deconstructed in some way. I realize that nested() is
> in a tight spot here to do anything about it since it doesn't exist.
> This behavior makes it hard for me to use the with statement (using
> nested()) the way I want.
> 
> Has anyone else been running in to this? Any tips on how to handle
> multiple resources?

Your problem does not seem to be connected to context managers. The error 
occurs before calling `contextlib.nested` at all::

   >>> foo = [Foo('a')]
   ctor a
   >>> with nested(*foo) as a: print a
   ... 
   __enter__ a
   [<__main__.Foo object at 0x7fbc29408b90>]
   __exit__ a
   >>> foo = [Foo('a'), Foo('b', True)]
   ctor a
   ctor b
   Traceback (most recent call last):
 File "", line 1, in 
 File "", line 7, in __init__
   raise Exception()
   Exception

If you need to deconstruct object `a` from your example, your staging is 
probably broken. Allocate the resource in `__init__` but only go live 
just in `__enter__`. If you do not enter the context, then, you won't 
need to deconstruct it as well.

HTH,

-- 
Robert "Stargaming" Lehmann
--
http://mail.python.org/mailman/listinfo/python-list


Re: Triple-quoted strings hath not the Python-nature

2008-10-21 Thread Robert Lehmann
On Tue, 21 Oct 2008 21:58:57 +1300, Lawrence D'Oliveiro wrote:

> If triple-quoted strings had the Python-nature, then they would take
> indentation into account. Thus:
> 
> """this
>  is a
>  multi-line
> string."""
> 
> would be equivalent to
> 
> "this\n is a\n multi-line\nstring."
> 
> and not
> 
> "this\n is a\n multi-line\nstring."
> 
> The rule would be: the exact same whitespace characters at the beginning
> of the line on which the triple-quoted string starts must also occur at
> the start of the lines on which the string continues; these are stripped
> off and not included in the string contents. Any additional whitespace
> is of course part of the string.

"Although practicality beats purity." -- The Zen of Python, by Tim Peters

I would feel greatly offended if I had to indent all *raw* data.

-- 
Robert "Stargaming" Lehmann
--
http://mail.python.org/mailman/listinfo/python-list


Re: Overloading operators

2008-10-15 Thread Robert Lehmann
On Wed, 15 Oct 2008 14:34:14 +0200, Mr.SpOOn wrote:

> Hi,
> in a project I'm overloading a lot of comparison and arithmetic
> operators to make them working with more complex classes that I defined.
> 
> Sometimes I need a different behavior of the operator depending on the
> argument. For example, if I compare a object with an int, I get a
> result, but if I compare the same object with a string, or another
> object, I get another result.
> 
> What is the best way to do this? Shall I use a lot of "if...elif"
> statements inside the overloaded operator? Or is there a more pythonic
> and dynamic way?

If all your comparison methods do more or less the same (even if not but 
then it will be kinda less useful for complex operations) you could use 
dictionary-based dispatching. You would basically construct a dictionary 
of type->comparator mappings, like this::

dispatch = {
int: int_compare_function,
str: str_compare_function,
}

And dispatch according to the other object's type::

def __cmp__(self, other):
return dispatch[type(other)]()

(Assuming good faith and just throwing a `KeyError` for unimplemented 
types.)

If you just needed to dispatch on a special attribute depending on the 
other object's type, you could redesign the dispatch dictionary to be a 
type->attribute mapping and go somewhere along this way::

dispatch = {
int: 'value',
str: 'name',
}
def __cmp__(self, other):
return cmp(getattr(self, dispatch[type(other)]), other)

HTH,

-- 
Robert "Stargaming" Lehmann
--
http://mail.python.org/mailman/listinfo/python-list


Re: Comparing float and decimal

2008-09-23 Thread Robert Lehmann
On Tue, 23 Sep 2008 07:20:12 -0400, D'Arcy J.M. Cain wrote:

> I'm not sure I follow this logic.  Can someone explain why float and
> integer can be compared with each other and decimal can be compared to
> integer but decimal can't be compared to float?

In comparisons, `Decimal` tries to convert the other type to a `Decimal`. 
If this fails -- and it does for floats -- the equality comparison 
renders to False. For ordering comparisons, eg. ``D("10") < 10.0``, it 
fails more verbosely::

  TypeError: unorderable types: Decimal() < float()

The `decimal tutorial`_ states:

  "To create a Decimal from a float, first convert it to a string. This  
  serves as an explicit reminder of the details of the conversion 
  (including representation error)."

See the `decimal FAQ`_ for a way to convert floats to Decimals.


 from decimal import Decimal
 i = 10
 f = 10.0
 d = Decimal("10.00")
 i == f
> True
 i == d
> True
 f == d
> False
> 
> This seems to break the rule that if A is equal to B and B is equal to C
> then A is equal to C.

I don't see why transitivity should apply to Python objects in general.

HTH,

.. _decimal tutorial: http://docs.python.org/lib/decimal-tutorial.html
.. _decimal FAQ: http://docs.python.org/lib/decimal-faq.html

-- 
Robert "Stargaming" Lehmann
--
http://mail.python.org/mailman/listinfo/python-list


Re: variable question

2008-07-11 Thread Robert Lehmann
On Fri, 11 Jul 2008 20:13:04 -0700, happy wrote:

> Can a variable be considered the simplest of the data structures. I am
> tutoring some kids about basics of programming using python. Not an
> expert in computer sciences, but am a python enthusiast.

Why do you need this additional layer of indirection? Just explain the 
real simple data structures à la "look, kids, a string is a chain of 
characters which are bytes actually. ". Although explaining encodings is an *important* thing (which 
many programmers still get wrong), it might be second priority to kids 
and you might just want to say "a string is text" and jump into higher-
order data structures.

> I wanted to know if it is correct to say a variable is a data structure,
> it has a name and a value. 

Not at all. This sounds a lot like an explanation for variables in other 
languages (such as C, where the value also has a type). In Python, we use 
to speak of "names," not variables. They are more like name tags you can 
put on objects -- or you don't. Depending on the age/interest of your 
students, I'd insert an explanation about references, reference counting 
and garbage collection here (they usually find that quite understandable 
and it paves the way for The Real Stuff, even though you might argue that 
the refcounting gc is a CPython detail and might become obsolete with 
PyPy's rise ).

The important thing is really that Python's approach of references is 
nearly orthogonal to the common approach of variables. In other 
languages, variables are (as you described above) containers (a bucket, 
really!) in your memory where you can put stuff into. Assignment is 
usually a copy or pointer operation.
Python does not care at all about your memory. You have abstract objects 
(incidentally saved in your memory, okay) with names being one mechanism 
to reference them. Here, assignment is always a "put the left-hand side 
name tag onto the right-hand side object".

> Put a stack of variables in a special data
> structure called a dictionary where the each name associates to a value.
> If in a data structure, one uses numbers starting from 0 to describe the
> name, it becomes a list and  so forth

First off, you really put objects in your data structures. Names are a 
one-way mapping -- the object does not know which name tags are assigned 
to it.

Your explanation of dictionaries and lists sounds a little bit upside-
down (not the mapping name->value or number->value makes it a dict or 
list -- the data structure makes it a mapping with this and that 
behaviour).

HTH,

-- 
Robert "Stargaming" Lehmann
--
http://mail.python.org/mailman/listinfo/python-list

Re: Ternary operator alternative in Ptyhon

2008-06-17 Thread Robert Lehmann
On Tue, 17 Jun 2008 23:18:51 -0700, kretik wrote:

> I'm sure this is a popular one, but after Googling for a while I
> couldn't figure out how to pull this off.
> 
> Let's say I have this initializer on a class:
> 
>  def __init__(self, **params):

Why not ``__init__(self, mykey=None)`` in the first place?
 
> I'd like to short-circuit the assignment of class field values passed in
> this dictionary to something like this:
> 
>   self.SomeField = \
>  params.has_key("mykey") ? params["mykey"] : None)
> 
> Obviously I know this is not actual Python syntax, but what would be the
> equivalent? I'm trying to avoid this, basically:
> 
>  if params.has_key("mykey"):
>  self.SomeField = params["mykey"]
>  else:
>  self.SomeField = None
> 
> This is not a big deal of course, but I guess my main goal is to try and
> figure out of I'm not missing something more esoteric in the language
> that lets me do this.
> 
> Thanks in advance.

You're lucky -- Python 2.5 just grew a ternary if-construct. You'd use it 
like that::

self.SomeField = params["mykey"] if "mykey" in params else None
# or, generically: TRUE if CONDITION else FALSE

Notice the use of the `in` operator, which is recommended over 
`dict.has_key`.

HTH,

-- 
Robert "Stargaming" Lehmann
--
http://mail.python.org/mailman/listinfo/python-list


Re: Name lookup inside class definition

2008-06-17 Thread Robert Lehmann
On Tue, 17 Jun 2008 23:05:56 -0700, WaterWalk wrote:

> Hello. Consider the following two examples: class Test1(object):
> att1 = 1
> def func(self):
> print Test1.att1// ok
> 
> class Test2(object):
> att1 = 1
> att2 = Test2.att1  // NameError: Name Test2 is not defined
> 
> It seems a little strange. Why a class name can be used in a method
> while cannot be used in the class block itself? I read the "Python
> Reference Manual"(4.1 Naming and binding ), but didn't get a clue.

It's because functions actually defer the name lookup. So you can use 
*any* name in a function, basically. If it's there at the function's 
runtime (not its declaration time), you're okay.

During the execution of a class body, the class is not yet created. So 
you're running this ``Test2.att1`` lookup already (it has to be executed 
*now*, during the class creation) and fail because the class is not there.

You can still refer to the class' scope as a local scope::

>>> class A(object):
...  att1 = 1
...  att2 = att1 + 2
...
>>> A.att1
1
>>> A.att2
3

HTH,

-- 
Robert "Stargaming" Lehmann
--
http://mail.python.org/mailman/listinfo/python-list


Re: generator functions: why won't this work?

2008-04-04 Thread Robert Lehmann
On Wed, 02 Apr 2008 19:04:30 -0300, Gabriel Genellina wrote:

> En Wed, 02 Apr 2008 14:11:30 -0300, <[EMAIL PROTECTED]> escribió:
> 
>> On Apr 1, 10:42 pm, "Gabriel Genellina" <[EMAIL PROTECTED]> wrote:
>>> En Tue, 01 Apr 2008 23:56:50 -0300, <[EMAIL PROTECTED]>
>>> escribió:
>>>
>>>    yield *iterable
>>>
>>> could be used as a shortcut for this:
>>>
>>>    for __temp in iterable: yield __temp
>>
>> How serious were you about that?
> 
> Not so much, I haven't thougth enough on it. Looks fine in principle,
> but yield expressions may be a problem.

Issue 2292: "Missing *-unpacking generalizations"
http://bugs.python.org/issue2292

Discussion on python-3000.devel:
http://thread.gmane.org/gmane.comp.python.python-3000.devel/12131

-- 
Robert "Stargaming" Lehmann
-- 
http://mail.python.org/mailman/listinfo/python-list

Re: Running a python program as main...

2008-03-26 Thread Robert Lehmann
On Wed, 26 Mar 2008 13:05:55 -0300, Gabriel Genellina wrote:

> En Wed, 26 Mar 2008 11:12:21 -0300, waltbrad <[EMAIL PROTECTED]>
> escribió:
> 
>> Stumbling through Mark Lutz's "Programming Python 3rd",  he gives an
>> example of a program that will automatically configure environment
>> settings and launch other programs.  Then he gives an example of
>> running this program. On  his command line he types:
>>
>> C:\...\PP3E>Launcher.py
>>
>> and this begins the program.  Doesn't work for me. I have to type:
>>
>> C:\...\PP3E>python Launcher.py
>>
>> Is this a typo on his part or has he configured his settings in such a
>> way that the command line will automatically associate the extension
>> with the program? (If so, he didn't mention this in his book).
> 
> I think it is an option in the installer, to associate or not Python to
> the .py extension.
> You could reinstall Python paying attention to the options, or repair
> the association as described in this thread:
> http://groups.google.com/group/comp.lang.python/browse_thread/thread/
b1d0fd05b3615057/


See also the official (development version of the) documentation with the 
new section "Using Python". "Using Python on Windows" covers exactly this 
topic:
http://docs.python.org/dev/using/windows.html#executing-scripts

HTH,

-- 
Robert "Stargaming" Lehmann
-- 
http://mail.python.org/mailman/listinfo/python-list