Few things

Josiah Carlson jcarlson at uci.edu
Tue Nov 30 13:18:59 EST 2004


bearophileHUGS at lycos.com (bearophile) wrote:
> 
> Thank you for the comments and answers, and sorry for my answering
> delay...
> 
> Josiah Carlson:
> 
> >Decorators can do this without additional syntax. Think @accepts and
> @returns.<
> 
> The purpose of those pre-post is to write something simile and very
> *clean* that states what inputs and outputs must be. This is an
> example of a pre-post conditional for a sorting function taken from
> that site (all this is inside the docstring of the function):
> 
> pre:
>     # must be a list
>     isinstance(a, list)
> 
>     # all elements must be comparable with all other items
>     forall(range(len(a)),
>            lambda i: forall(range(len(a)),
>                             lambda j: (a[i] < a[j]) ^ (a[i] >= a[j])))
> 
> post[a]:
>     # length of array is unchanged
>     len(a) == len(__old__.a)
> 
>     # all elements given are still in the array
>     forall(__old__.a, lambda e: __old__.a.count(e) == a.count(e))
> 
>     # the array is sorted
>     forall([a[i] >= a[i-1] for i in range(1, len(a))])

That is simple and clean?  In my opinion, if one wants to write such
complicated pre and post conditions, one should have to write the pre
and post condition functions that would do the test, and either use
decorators, or use calls within the function to do the tests.  That is
the way it is done now, and I personally don't see a good reason to make
a change.  Then again, I document and test, and haven't used pre/post
conditions in 5+ years.


> Surely such things can be passed (at least as strings) to the @accepts
> and @returns decorators (using a "decorate" identifier instead of @ is
> probably nicer, because the @ makes Python look more like Perl, but
> I've seen that lots of people have already discussed such topic). Such
> testing performed by such decorators can be "switched off" with a
> global boolean flag when the program is debugged and tested.
> So now someone can write and let standardise a couple of good @accepts
> and @returns decorators/functors :-]

Discussion of the @ decorator syntax is a moot point.  Python 2.4 final
was released within the last couple days and uses @, which Guido has
decided is the way it will be.  You are around 6 months too late to have
anything to say about what syntax is better or worse.  It is done.


> >Having a 'faq' for permutation and combination generation would be
> 99% of the way there.<
> 
> Uh, I'm sorry, but I don't understand :-]
> Aren't such functions quite well defined?

Think of it like an 'example' in the documentation, where the code is
provided for doing both permutations and combinations.  There exists a
FAQ for Python that addresses all sorts of "why does Python do A and not
B" questions.  Regardless, both are offered in the Python cookbook.


> >[Fixed] Quickselect, really, doesn't gain you a whole lot. Sure, it's
> a log factor faster to select a median, but many algorithms involving
> selecting medians (at least the ones that I run into in CS theory) end
> up repeatedly (logn times) selecting the 'kth' smallest element
> (varying k's), where sorting would actually run slightly faster.<
> 
> I've done some tests with a Quickselect that I have essentially
> translated and adapted to pure Python from "Numerical Recipes" (it
> seems a bit faster than the Quickselect coded by Raymond Hettinger
> that can be seen in the cookbook). I have seen that on my PC, on
> random sequence of FP numbers, a *single* Quickselect (to find just
> the median) is faster than the standard sort for lists longer than
> about 3 million elements. So it's often useless.
> But using Psyco, that Quickselect becomes 5-6 times faster (for long
> lists), so it beats the (good) standard Sort for lists longer than
> 600-3000 elements. If the Quickselect works in place (as the sort)
> then it returns a partially ordered list, and you can use it to
> quickly select other positions (so for close positions, like the
> computing of the two central values for the median, the complexity of
> the second select is nearly a constant time).
> So coding the Quickselect in C/Pyrex can probably make it useful.
> If you are interested I can give the Python Quickselect code, etc.

No thank you, I have my own.


> Nick Coghlan>I believe the OP was objecting to the spelling of "this
> integer literal is hex" and "this integer literal is octal".<
> 
> Right.
> 
> 
> Josiah Carlson>Regardless, I also don't believe the "I don't like
> this" without "this is the way it should be" will result in anything.<
> 
> You are right, I was mostly afraid of saying silly things... Here is:
> Such syntax can be like:
> number<Separator><Base>
> 
> (Putting <Base><Separator> at the beginning of the number is probably
> worse and it goes against normal base representation in mathematics,
> where you often subscript the base number).
> 
> <Separator> cannot be "B" or "b" (that stands for "base") because
> number can be a Hex containing B too... So <Separator> can be "_"
> (this is the Subscript in TeX markup, so this agrees with normal
> representation of the base)
> 
> <Base> can be:
> 1)just an integer number representing the base (similar to the second
> parameter of "int", this also allows to specify any base).
> 2) a symbol to represent a smaller class of possibilities, like 0=2,
> 1=8, 2=10, 3=16, 4=64. Instead
> of such digits a letter can be used: a=2, b=8, c=10, etc.
> I think the first option is better.
> 
> So integer numbers can be written like:
> 1010100111011_2
> 154545_10
> 777_8
> afa35a_16
> Fi3pK_64

Ick.  In Python, the language is generally read left to right, in a
similar fashion to english.  The prefix notation of 0<octal> and 0x<hex>,
in my opinion, reads better than your postfix-with-punctuation notation.

I'll also mention that two of your examples; afa35a_16 and Fi3pK_64, are
valid python variable names through all of the Python versions I have
access to, so are ambiguous if you want to represent 'integer literals',
which have historically been 'unquoted strings prefixed with a number'.

Furthermore, there /is/ already a postfix notation for representing
integers, though it doesn't support all bases at the moment, requires
a bit more punctuation, and is runtime-evaluated:

>>> int('1010', 2)
10
>>> int('1010100111011',2)
5435
>>> int('154545',10)
154545
>>> int('777',8)
511
>>> int('afa35a',16)
11510618
>>> int('Fi3pK',64)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: int() base must be >= 2 and <= 36
>>>


Your second option (replacing the _2, _10, etc., with _1, _2, ...) is,
in my opinion, shit.  You take something that is unambiguous (base
representation) and make it ambiguous through the use of a numbering of
a set of 'standard' bases.  What is the use of representing base 10 as a
'2' or 'c'?  I cannot think of a good reason to do so, unless being
almost unreadable is desireable.


An option if you want to get all of the base representations available
is a prefix notation that is similar to what already exists.  I'm not
advocating it (because I also think its crap), but the following fixes
the problems with your postfix notation, and is explicit about bases.
0<base>_<number>
like:
016_feff
02_10010010101
010_9329765872
08_767

The above syntax is:
1. unambiguous
2. readable from left-to-right

Note that I think that the syntax that I just provided is ugly.  I much
prefer just using decimal and offering the proper base notation
afterwards in a comment...

val = 15 # 1111 in binary
val = 35 # 0x23 in hex
val = 17 # 021  in octal


 - Josiah




More information about the Python-list mailing list