Re: How can a function find the function that called it?
kj no.em...@please.post writes: But OrderedDict's functionality *requires* that its __init__ be run, and this __init__, in turn, does part of its initialization by calling the update method. Therefore, the update method of the new subclass needs to be able to identify the calling function in order to make a special allowance for calls coming from OrderedDict.__init__ That doesn't follow at all. Why not set a `frozen' flag when your initialization is complete? Something like class ImmutableOrderedDict (OrderedDict): def __init__(me, *args, **kw): me._frozen = False OrderedDict.__init__(me, *arg, **kw) me._frozen = True def _check(me): if me._frozen: raise ImmutableError And so on. Thank you for explaining your actual objective, by the way. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Regular expression for key = value pairs
Ciccio franap...@gmail.com writes: suppose I have: s='a=b, c=d' and I want to extract sub-strings a,b,c and d from s (and in general from any longer list of such comma separated pairs). [...] In [12]: re.findall(r'(.+)=(.+)', s) Out[12]: [('a=b, c', 'd')] I think there are two logically separate jobs here: firstly, extracting the comma-separated pairs, and secondly parsing the individual pairs. If you want the extra problem of dealing with regular expressions, this seems to be the way to do it. R_PAIR = re.compile(r''' ^\s* ([^=\s]|[^=\s][^=]*[^=\s]) \s*=\s* (\S|\S.*\S) \s*$ ''', re.X) def parse_pair(pair): m = R_PAIR.match(pair) if not m: raise ValueError, 'not a `KEY = VALUE\' pair' return m.groups([1, 2]) The former is even easier. R_COMMA = re.compile(r'\s*,\s*') kvs = [parse_pair(p) for p in R_COMMA.split(string)] Apply gold-plating to taste. But actually, it's much easier to avoid messing with regular expressions at all. def parse_pair(pair): eq = pair.index('=') return pair[:eq].strip(), pair[eq + 1:].strip() kvs = [parse_pair(p) for p in string.split(',')] -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Regular expression for key = value pairs
André andre.robe...@gmail.com writes: How about the following: s = 'a=b,c=d' t = [] for u in s.split(','): ... t.extend(u.split('=')) s = 'a = b = c, d = e' = ['a ', ' b ', ' c', ' d ', ' e'] Ugh. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
Steve Holden st...@holdenweb.com writes: I think the choice of keyword is probably not Guido's crowning language achievement, I remember the behaviour by considering a typical application: for thing in things: if shinyp(thing): break else: raise DullError, 'nothing shiny found' In this kind of search loop, `break' signifies a kind of successful completion: the `for' loop can be considered to be a test acting over an iterable, and `else' therefore denotes the action if the test fails. I don't know whether that's the official intuition, or even if there is an official intuition, but it works well enough for me. I'm quite fond of Python's extra `else' clauses in `for' and (particularly) `try'. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: PyArg_ParseTuple question
Mark Crispin nos...@panda.com writes: In a C module, I want to pick up the arguments for a Python call like: module.call(string1,[string2a, string2b, string2c], string3) and stash these into: char *arg1; char *arg2[]; char *arg3; All arguments are required, and we can assume that the arg2 vector is terminated with a null pointer. It doesn't look like PyArg_ParseTuple will do this easily; and that instead I have to use either the O! format with a PyList prototype, or use O and write a converter. I think the latter is probably your best bet. If I use O!, at what level does it check? In particular, does it just check that the argument is a list, so I can get away with something like: It does the equivalent of `isinstance', so you'll accept a `list' or an instance of any subclass of `list'. The `O' converter is pretty straightforward. Something like this ought to do. static int convertlist(PyObject *o, void *p) { PyObject **v; Py_ssize_t i, n; /* Could allow general sequences using PySequence_Fast */ if (!PyList_Check(o)) return (0); /* Copy stuff */ n = PyList_GET_SIZE(o); if ((v = PyMem_New(PyObject *, n + 1)) == 0) return (0); for (i = 0; i n; i++) { v[i] = PyList_GET_ITEM(o, n); Py_INCREF(v[i]); } v[n] = 0; return (1); } If you want to do a more complex conversion (e.g., to the individual items) there's more work to be done. I could have used PySequence_* functions to read the size and items, but that makes error handling more complicated. One could also borrow the references from the underlying list, which would leave the underlying storage for the vector as the only thing to free. I ended up writing a lot of conversion functions when I was doing Python library bindings (for a crypto library); they're generally a good thing. I found that the trickiest thing about PyArg_ParseTuple is in making sure that you can clean everything up even if it goes wrong half way through. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Comparisons of incompatible types
Steven D'Aprano steve+comp.lang.pyt...@pearwood.info writes: On Thu, 09 Dec 2010 12:21:45 +, Mark Wooding wrote: John Nagle na...@animats.com writes: sort has failed because it assumes that a b and b c implies a c. But that's not a valid assumption here. It's not good to break trichotomy. You're confused. The property a b and b c = a c is called `transitivity'. Yes, but I believe that John is referring to the trichotomy (like a dichotomy, Then why did he say `it assumes that a b and b c implies a c'? This assumption is transitivity, not trichotomy. 2. Totality: a = b or b = a The above list sorting goes wrong because the `float' ordering isn't total. In particular, x /= NaN and NaN /= x for all x (including x = NaN!). I believe this is equivalent to trichotomy. No, it isn't. In particular, the definition of totality I gave above allows a = b and b = a and a /= b. You gave a perfectly good definition of trichotomy, which I have moved out of its original order: exactly one of these relations are true: a b a == b a b A total preorder (as defined above) doesn't exhibit this property -- but can be described in terms of a total order (which /does/ exhibit proper trichotomy) applied to a set of equivalence classes. So, your last remark is in the right direction (though strict trichotomy is unnecessary, as I've mentioned), but apparently only by accident since the preceding discussion is completely wrong. Completely is surely a tad strong -- John might not be using the exact same terminology as you, but he's clearly talking about the equivalent concepts. He wants and expects all data types to either meet a total order, or raise an exception to any of the = and = operators. No. He was hopelessly confused, describing the problem in terms of a failure of transitivity (which doesn't, in fact, fail), but using the word `trichotomy', apparently more by luck than judgement. I don't want to insist on a total order. Efficient sorting requires a total preorder, and that's all I want. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Comparisons of incompatible types
John Nagle na...@animats.com writes: NaN = float(nan) arr = [1.0, 4.0, 3.0, 2.0, 5.0, NaN, 6.0, 3.0, NaN, 0.0, 1.0, 4.0, 3.0, 2.0, 5.0, NaN, 6.0, 3.0, NaN, 0.0] sorted(arr) [0.0, 0.0, 1.0, 1.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 4.0, 5.0, nan, 5.0, 6.0, nan, 4.0, nan, 6.0, nan] The sorted numerical values aren't in order. Indeed. You failed to provide a valid ordering to `sorted'. By failing to satisfy its precondition, you relieved it of its obligation to satisfy its postcondition. sort has failed because it assumes that a b and b c implies a c. But that's not a valid assumption here. It's not good to break trichotomy. You're confused. The property a b and b c = a c is called `transitivity'. But the `float' ordering /is/ transitive. Note that a b implies that neither a nor b is a NaN. Also, trichotomy is unnecessary for sorting, and Python's `sort' method doesn't require it; it does require a total preorder, though. What properties does a total preorder require? 1. Transitivity: a = b and b = c = a = c 2. Totality: a = b or b = a The above list sorting goes wrong because the `float' ordering isn't total. In particular, x /= NaN and NaN /= x for all x (including x = NaN!). So, your last remark is in the right direction (though strict trichotomy is unnecessary, as I've mentioned), but apparently only by accident since the preceding discussion is completely wrong. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Comparison with False - something I don't understand
OKB (not okblacke) brennospamb...@nobrenspambarn.net writes: This is an interesting setup, but I'm not sure I see why you need it. If you know that, in a particular context, you want toy(x, 0) to result in 42 instead of ZeroDivisionError, ... and that's the point. You don't know whether you'll need it at the call site. Something further up has decided that, in its context, 42 shall be the magic value returned. In some other context, there shouldn't be a magic value, and the exception should terminate the program. My toy example was just that: a minimal example showing the machinery in action. The value of separating out exception handling like this is only apparent if there's a fair amount of code in between the policy (`return 42') and the site where the exception is signalled. Small examples of powerful abstractions aren't very convincing: a small example trivially doesn't require powerful abstraction. Sorry. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Exception handling in Python 3.x
John Nagle na...@animats.com writes: PEP 255, like too much Python literature, doesn't distinguish clearly between the language definition and implementation detail. It says The mechanics of StopIteration are low-level details, much like the mechanics of IndexError in Python 2.1. Applications shouldn't be explicitly using StopIteration. You've twisted the words by quoting them out of context, and have attempted to force a misinterpretation of `low-level details' as `implementation detail'. That text comes from a question-and-answer section, in response to the question `why not force termination to be spelled StopIteration?'. This is a fine answer to the question: the details of the (preexisting -- see PEP 234) iteration protocol are abstracted by the generator syntax. But it doesn't at all mean that the StopIteration exception isn't an official, use-visible part of Python. IronPython doesn't do StopIteration the same way CPython does. http://ironpython.codeplex.com/wikipage?title=IPy1.0.xCPyDifferences IronPython's behaviour when you try to fetch items from a spent generator is different. It still implements the same iterator protocol, and raises StopIteration when it has no more items to yield. You're not stupid, but you'd have to be in order to think that these references support your claim that You're not entitled to assume that StopIteration is how a generator exits. That's a CPyton thing; generators were a retrofit, and that's how they were hacked in. Other implementations may do generators differently. I don't want to conclude that you're not arguing in good faith but I'm not seeing many other possibilities. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Comparisons of incompatible types
John Nagle na...@animats.com writes: [Stepanov] makes the point that, for generic programs to work right, the basic operations must have certain well-defined semantics. Then the same algorithms will work right across a wide variety of objects. This is consistent with Python's duck typing, but inconsistent with the current semantics of some operators. This isn't a disaster. You should check that the arguments define the necessary operations and obey the necessary axioms. Python is already dynamically typed: this kind of proof-obligation is already endemic in Python programming, so you've not lost anything significant. For example, + as concatenation makes + non-commutative. In other words, a + b is not always equal to b + a which is not good. I think I probably agree with this. Concatenation yields a nonabelian monoid (usually with identity); `+' is pretty much universally an abelian group operator (exception: natural numbers, where it's used in an abelian monoid which extends to a group in a relatively obvious way). But then we'd need another operator symbol for concatenation. Nonnegative integers act on strings properly, but the action doesn't distribute over concatenation, which is also a shame. i.e., n*(a + b) != n*a + n*b But it's a familiar notation, by no means peculiar to Python, and changing it would be difficult. Exactly one of a b a = b a b is true, or an type exception must be raised. This will get the numerical people screaming. Non-signalling NaNs are useful, and they don't obey these axioms. I think, more generally, that requiring a full total order (rather than either a preorder or a partial order) is unnecessarily proscriptive. Sorting only requires a preorder, for example, i.e., { (a, b) | a = b = a } is an equivalence relation, and the preorder naturally induces a total order on the equivalence classes. Topological sorting requires only a partial order, and makes good use of the notation. As an example, sets use `=' to denote subsetness, which is well known to be a partial order. (I presume you weren't going to deny a = b iff a b or a == b or a b iff b a because that really would be bad.) The basic Boolean identities (a or b) == (b or a) not (a or b) == (not a) and (not b) not (not a) == a should all hold, or an type exception should be raised. The first of these contradicts the axiom x = x or _|_ == x which is probably more useful. The last can't usefully be true since `not' is lossy. But I think that, for all values a, b, not (a or b) == not (b or a) == (not a) and (not b) not (not (not a)) == not a which is probably good enough. (The application of `not' applies a boolean coercion, which canonifies adequately.) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Comparisons of incompatible types
Carl Banks pavlovevide...@gmail.com writes: I think that feeling the need to sort non-homogenous lists is indictative of bad design. Here's a reason you might want to. You're given an object, and you want to compute a hash of it. (Maybe you want to see whether someone else's object is the same as yours, but don't want to disclose the actual object, say.) To hash it, you'll need to serialize it somehow. But here's a problem: objects like dictionaries and sets don't impose an ordering on their elements. For example, the set { 1, 'two' } is the same as the set { 'two', 1 } -- but iterating the two might well yield the elements in a different order. (The internal details of a hash table tend to reflect the history of operations on the hash table as well as its current contents.) The obvious answer is to apply a canonical ordering to unordered objects like sets and dictionaries. A set can be serialized with its elements in ascending order; a dictionary can be serialized as key/value pairs with the keys in ascending order. But to do this, you need an (arbitrary, total) order on all objects which might be set elements or dictionary keys. The order also needs to be dependent only on the objects' serializable values, and not on any incidental facts such as memory addresses or whatever. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Comparison with False - something I don't understand
Paul Rubin no.em...@nospam.invalid writes: You know, I've heard the story from language designers several times over, that they tried putting resumable exceptions into their languages and it turned out to be a big mess, so they went to termination exceptions that fixed the issue. That seems very surprising to me. Are there any languages out there with resumable exceptions? Common Lisp and Smalltalk spring to mind. It's fairly straightforward to write one in Scheme. (Actually, implementing the Common Lisp one in terms of fluids, closures and blocks isn't especially difficult.) Escaping to a debugger doesn't really count as that. Indeed not. I guess one way to do it would be call a coroutine to handle the exception, and either continue or unwind after the continue returns, but doing it in a single-threaded system just seems full of hazards. It seems pretty straightforward to me. Handlers are simply closures; the registered handlers are part of the prevailing dynamic context. When an exception occurs, you invoke the handlers, most-recently registered first. A handler that returns normally can be thought of as `declining' to handle the exception; a handler that explicitly transfers control elsewhere can be thought of as having handled it. To make this work, all you need is: * a fluid list (i.e., one which is part of the dynamic context) of handlers, which you can build in pure Python if you try hard enough (see below); * closures to represent handlers, which Python has already, and; * a nonlocal transfer mechanism, and a mechanism like try ... finally to allow functions to clean up if they're unwound. We can actually come up with a nonlocal transfer if we try, by abusing exceptions. [The code in this article is lightly tested, but probably contains stupid bugs. Be careful.] class block (object): Context manager for escapable blocks. Write with block() as escape: ... Invoking the `escape' function causes the context body to exit immediately. Invoking the `escape' function outside of the block's dynamic context raises a ValueError. def __init__(me): me._tag = None def _escape(me, value = None): if me._tag is None: raise ValueError, 'defunct block' me.result = value raise me._tag def __enter__(me, value = None): if me._tag: raise ValueError, 'block already active' me._tag = type('block tag', (BaseException,), {}) me.result = value return me._escape def __exit__(me, ty, val, tb): tag, me._tag = me._tag, None return ty is tag This is somewhat brittle, since some intervening context might capture the custom exception we're using, but I don't think we can do significantly better. Implementing fluids badly is easy. Effectively what we'd do to bind a fluid dynamically is try: old, fluid = fluid, new ... finally: fluid = old but this is visible in other threads. The following will do the job in a multithreaded environment. import threading as T import weakref as W class FluidBinding (object): Context object for fluid bindings. def __init__(me, fluid, value): me.fluid = fluid me.value = value def __enter__(me): me.fluid._bind(me.value) def __exit__(me, ty, val, tb): me.fluid._unbind() class Fluid (object): Represents a fluid variable, i.e., one whose binding respects the dynamic context rather than the lexical context. Read and write the Fluid through the `value' property. The global value is shared by all threads. To dynamically bind the fluid, use the context manager `binding': with myfluid.binding(NEWVALUE): ... The binding is visible in functions called MAP within the context body, but not in other threads. _TLS = T.local() _UNBOUND = ['fluid unbound'] _OMIT = ['fluid omitted'] def __init__(me, value = _UNBOUND): Iinitialze a fluid, optionally setting the global value. me._value = value @property def value(me): Return the current value of the fluid. Raises AttributeError if the fluid is currently unbound. try: value, _ = me._TLS.map[me] except (AttributeError, KeyError): value = me._value if value == me._UNBOUND: raise AttributeError, 'unbound fluid' return value @value.setter def value(me,
Re: Resumable exceptions bad:
John Nagle na...@animats.com writes: Resumable exceptions were a popular idea in the early days of programming. LISP, PL/I, and early COBOL had constructs which could be considered resumable exceptions. They didn't work out well, because the exception handler gets control in an ambiguous situation, perhaps in the middle of an expression. Changing the state of the execution, then returning, can leave the program in an invalid state. Right, but that's not the important really important trick. The important bit is separating out the `how should I fix this?' logic from the point where execution should resume. There's no good reason why the former should have to come from a dynamic context smaller than the latter: it's just an unnecessary conflation. [Snip stuff about signals. I agree that Unix signals are a disaster.] So that's why resumable exceptions are a bad idea. That's why a primitive resumable exception system, used naively, is a bad idea. Now look at the good ones. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Comparisons of incompatible types
Terry Reedy tjre...@udel.edu writes: And indeed, code like this that has not been updated does break in 3.x. to some people's annoyance. We really really cannot please everyone ;-). The problem is that there are too many useful properties that one might expect from comparison operators. For example, it's frequently nice to have a total ordering on all objects. For real numbers, it's nice that the ordering obey the usual ordered-field axioms; but the complex numbers don't have an ordering compatible with the field operators, and imposing a default ordering (e.g., degree-lexicographic) is probably asking for trouble. I agree that the Python 3 behaviour is an improvement, by the way. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Exception handling in Python 3.x
John Nagle na...@animats.com writes: Right. You're not entitled to assume that StopIteration is how a generator exits. That's a CPyton thing; generators were a retrofit, and that's how they were hacked in. Other implementations may do generators differently. This is simply wrong. The StopIteration exception is a clear part of the generator protocol as described in 5.2.8 of the language reference; the language reference also refers to 3.5 of the library reference, which describes the iterator protocol (note, not the generator implementation -- all iterators work the same way), and explicitly mentions StopIteration as part of the protocol. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Comparison with False - something I don't understand
Carl Banks pavlovevide...@gmail.com writes: On Dec 6, 12:58 pm, m...@distorted.org.uk (Mark Wooding) wrote: def toy(x, y): r = restart('use-value') with r: if y == 0: error(ZeroDivisionError()) r.result = x/y return r.result def example(): def zd(exc): if not isinstance(exc, ZeroDivisionError): return r = find_restart('use-value') if not r: return r.invoke(42) print toy(5, 2) with handler(zd): print toy(1, 0) You could do that. Or, you could just put your try...finally inside a loop. [You correct `finally' to `except' in a follow-up.] I think you've missed the point almost entirely. Any code called from within the `with handler' context will (unless overridden) cause a call `toy(x, 0)' to return 42. Even if the `with handler' block calls other functions and so on. Note also that the expression of this is dynamically further from where the error is signalled than the resume point (which is within the same function). You can't do this with `try' ... `except'. Which was, of course, the point. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Comparison with False - something I don't understand
Steven D'Aprano steve+comp.lang.pyt...@pearwood.info writes: On Thu, 02 Dec 2010 16:35:08 +, Mark Wooding wrote: There are better ways to handle errors than Python's exception system. I'm curious -- what ways would they be? The most obvious improvement is resumable exceptions. In general, recovering from an exceptional condition requires three activities: * doing something about the condition so that the program can continue running; * identifying some way of rejoining the program's main (unexceptional) flow of control; and * actually performing that transfer, ensuring that any necessary invariants are restored. Python's `try ... finally' helps with the last; but Python intertwines the first two, implementing both with `try ... except'. The most important consequence of this is that the logic which contains knowledge about how to fix the condition must be closer to the code that encountered the condition than the resume point is. It's therefore hard to factor out high-level policy about fixing conditions from the relatively tedious business of providing safe points at which to resume main execution. (Effectively, each section of your program which wants to avail itself of some high-level condition-fixing policy has to provide its own protocol for expressing and implementing them.) Phew. That was abstract. Can I come up with some examples? I've been writing a (sort of) compiler recently. When it encounters errors, it reports a message to the user containing the position it had reached in the source, updates a counter so that it can report a summary at the end of the run and produce a sensible exit status, and then attempts to carry on compiling as best it can. The last bit -- attempting to carry on as best it can -- needs local knowledge of what the compiler's doing and what actually went wrong. If the parser expected to find a delimiter, maybe it should pretend that it found one, for example. The other stuff, printing messages, updating counters, and so on, is all done with some condition handlers wrapped around the meat of the compiler. That's written only once. Everything that signals errors, including standard I/O functions like open-a-file, gets the same treatment. (The remaining missing ingredient is a fluid variable which tracks the current position in the source and is updated by the scanner; bits of the compiler's semantic analysis machinery will temporarily focus attention on other parts of the source using locations they saved during the parse. Implementing fluids in Python can be done with a context manager: if you don't care about concurrency then you can use simple variables; otherwise it's little fiddly and the syntax isn't very comfortable, but it's still possible.) A more familiar example, maybe, is the good old DOS `abort/retry/fail' query. Implementing such a thing in Python, as a general policy for handling I/O errors, isn't possible. Viewed narrowly, this is probably a good thing: the old DOS query was very annoying. But the difficulty of implementing this policy illustrates the missing functionality. And, of course, if DOS had a proper resumable exception system, programs could have overridden the annoying query. In general, the code which discovers an exceptional condition may have several options for how to resume. It might be possible to ignore the situation entirely and carry on regardless (`false alarm!'). It might be possible to try again (`transient failure'). Alas, the logic which is capable of implementing these options is usually too low-level and too close to the action to be able to decide among them sensibly. (Maybe a human user should be consulted -- but that can drag in user interface baggage into a low-level networking library or whatever.) Resumable exceptions provide a way out of this mess by separating the mechanics of resumption from policy of which resumption option to choose. It's easy to show that a resumable exception system can do everything that a nonresumable system (like Python's) can do (simply put all of the recovery logic at the resume point); but the converse is not true. There are some other fringe benefits to resumable exceptions. * It's usual to report a stack backtrace or similar if an exception occurs but nothing manages to resume execution. If unwinding the stack is intertwined with working out how to resume execution, then whenever you /try/ to run an applicable handler, you have to reify the stack context and stash it somewhere in case the handler doesn't complete the job. This makes raising exceptions more expensive than they need to be. * You can use the same mechanism for other kinds of communication with surrounding context. For example, Python occasionally emits `warnings', which have their own rather simple management system (using global state, so it's hard to say `don't issue MumbleWarnings while we frob the widgets
Re: Assigning to __class__ attribute
kj no.em...@please.post writes: class Spam(object): pass Now I define an instance of Spam and an instance of Spam's superclass: x = Spam() y = Spam.__mro__[1]() # (btw, is there a less uncouth way to do this???) There's the `__bases__' attribute, which is simply a tuple of the class's direct superclasses in order. Spam.__bases__[0] will always be equal to Spam.__mro__[1] because of the way the linearization works. There's also `__base__' attribute, which seems to correspond to a PyTypeObject's `tp_base' slot; this /isn't/ always the first direct superclass; I'm not quite sure what the rules are, and it doesn't seem to be documented anywhere. [z.__class__.__name__ for z in x, y] ['Spam', 'object'] class Ham(object): pass ... x.__class__ = Ham [isinstance(x, z) for z in Spam, Ham] [False, True] First question: how kosher is this sort of class transmutation through assignment to __class__? Yep. That's allowed, and useful. Consider something like a red/black tree: red and black nodes behave differently from one another, and it would be convenient to make use of method dispatch rather than writing a bunch of conditional code; unfortunately, nodes change between being red and black occasionally. Swizzling classes lets you do this. Various other languages have similar features. The scariest is probably Smalltalk's `become: anObject' method, which actually swaps two objects. Python `__class__' assignment is similarly low-level: all it does is tweak a pointer, and it's entirely up to the program to make sure that the object's attributes are valid according to the rules for the new class. The Common Lisp Object System has CHANGE-CLASS, which is a rather more heavyweight and hairy procedure which tries to understand and cope with the differences between the two classes. I've never seen it done. Is this because it considered something to do only as a last resort, or is it simply because the technique is not needed often, but it is otherwise perfectly ok? It's not needed very often, and can be surprising to readers who aren't familiar with other highly dynamic object systems, so I don't think it's particularly encouraged; but it seems like it might be the best approach in some cases. I think it's one of those things where you'll just /know/ when it's the right answer, and if you don't know that it's the right answer, it isn't. y.__class__ = Ham Traceback (most recent call last): File stdin, line 1, in module TypeError: __class__ assignment: only for heap types `Heap types' are types which are allocated dynamically. Non-heap types are ones which are dreamt up by C extensions or built into Python. I suspect that the logic here is that non-heap types in general are magical and weird, and their instances might have special C stuff attached to them, so changing their classes is a Bad Idea, though there's an extra check which catches most problems: In [1]: class foo (str): pass In [2]: class bar (object): pass In [3]: x = foo() In [4]: x.__class__ = bar TypeError: __class__ assignment: 'foo' object layout differs from 'bar' Anyway, I'd guess it's just a bug that `object' is caught this way, but it doesn't seem an especially important one. This definitely rattles my notions of inheritance: since the definition of Spam was empty, I didn't expect it to have any significant properties that are not already present in its superclass. Yes, sorry. I think this is a bit poor, really, but it's hard to do a much better job. Pure Python objects are pretty simple things, really: they have a pointer to their class, and a bunch of attributes stored in a dictionary. What other languages call instance variables or methods are found using attribute lookup, which just searches the object, and then its class and its superclasses in the method resolution order. If you fiddle with `__class__', then attribute lookup searches a different bunch of classes. Nothing else needs to change -- or, at least, if it does, then you'd better do it yourself. Types implemented in C work by extending the underlying Python object structure. The magical type-specific stuff is stored in the extra space. Unfortunately, changing classes is now hard, because Python code can't even see the magic C stuff -- and, besides, a different special C type may require a different amount of space, and the CPython implementation can't cope with the idea that objects might move around in memory. Similar complications occur if one of the classes has a `__slots__' attribute: in this case, both the original and new class must have a `__slots__' attribute and they must be the same length and have the same names. What is the most complete, definitive, excruciatingly detailed exposition of Python's class and inheritance model? It's kind of scattered. The language reference sections 3.3 and 3.4 contain some useful information, but it's rather detailed and it's a (mostly) comprehensive list of what a bunch of
Re: Comparison with False - something I don't understand
Harishankar v.harishan...@gmail.com writes: There are some reasons why I hate exceptions but that is a different topic. However, in short I can say that personally: 1. I hate try blocks which add complexity to the code when none is needed. Try blocks make code much more unreadable in my view and I use it only for the built-in exceptions when absolutely needed. Very little code actually needs `try' blocks. 2. I prefer the less irksome True or False to do error checking. Exceptions seem too heavyweight for simple problems. Just write simple programs as if errors never happen; if an exception is raised, the program prints a vaguely useful message and exits. Besides, this complaint is incoherent. One needs at least as much structure to check an error code as to catch an exception. 3. Philosophically I think exception handling is the wrong approach to error management. There are better ways to handle errors than Python's exception system. Passing error codes around manually is most definitely not one of them. (One of the main reasons I ditched Perl in favour of Python is the former's insistence on returning error codes for I/O and system calls.) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Catching user switching and getting current active user from root on linux
Grant Edwards inva...@invalid.invalid writes: On 2010-11-30, mpnordland mpnordl...@gmail.com wrote: and catch user switching eg user1 locks screen, leaves computer, user2 comes, and logs on. basically, when there is any type of user switch my script needs to know. What do you do when there are multiple users logged in? In case it's not clear: this situation doesn't just occur on `exotic' systems like Unix servers. Even Windows systems can have several people logged into the console (with one active, using `fast user switching') and another one or two connected using terminal services. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Needed: Real-world examples for Python's Cooperative Multiple Inheritance
Steve Holden st...@holdenweb.com writes: It isn't. Even inheritance itself isn't as useful as it at first appears, and composition turns out in practice to be much more useful. That goes double for multiple inheritance. Composition /with a convenient notation for delegation/ works fairly well. Indeed, this can be seen as the basis of Self. But downwards delegation -- where a superclass leaves part of its behaviour unspecified and requires (concrete) subclasses to fill in the resulting blanks -- is hard to express like this without some kind of means of identifying the original recipient of the delegated message. Once you've done that, there isn't much of a difference between a superclass and a component with implicit delegation. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Needed: Real-world examples for Python's Cooperative Multiple Inheritance
John Nagle na...@animats.com writes: On 11/26/2010 4:21 PM, Mark Wooding wrote: John Naglena...@animats.com writes: @This catches the case where two classed both inherit from, say threading.thread, each expecting to have a private thread. Why on earth would anyone do such a bizarre thing? If you want a private thread, then attach one as an attribute. Inheriting is simply madness. This must be from someone who hasn't used threads in Python. Wrong again. The usual way to write a thread in Python is to subclass threading.thread. The subclass provides a run function, which will be called from the new thread. Yes, it is. Does that conflict with what I wrote? No. If you want you class to have a private thread, make /another/ class to represent the behaviour of this private thread, and attach an instance of this to the first class. Or you can pass a closure or a bound method to the thread constructor. (That's probably cleaner, actually, but doesn't fit culturally.) If you stopped whining about how Python's object system might theoretically go wrong if you try to use it like it was C++ and started thinking about how to actually make effective use of the features it offers -- features which long predate Python, and have been thought about over many years, in languages such as Zetalisp, Common Lisp, Dylan, Scheme, and variants of Smalltalk -- you might got on much better. Ah, fanboys. Not exactly. I collect programming languages like some people collect postage stamps; it gives one a useful perspective. I mentioned those languages because they seem most historically relevant. Zetalisp's `Flavors' system introduced multiple inheritance; Common Lisp and Dylan fix the linearization properly (eventually culminating in the C3 linearization algorithm); Scheme has no standardized object system, but there are a number of -- mainly CLOS-like -- object systems available; and Smalltalk is both the classic dynamic object-oriented language and a single-dispatch contrast to the CLOS/Dylan generic-functions approach. Of those, I've written code in Common Lisp, Scheme, and Smalltalk. Most of the LISP variants really did objects very well; objects were an afterthought. Smalltalk went a bit too far in the other direction; the everything is an object mindset was overdoing it. CLOS actually does a remarkable integration job, bringing the existing types into the object system; but, yes, the seams are still visible, because you can't subclass some of the classes. Python is reasonably well balanced in the object area. Everything isn't an object. There are explicit classes, unlike the instance-copying model of Self and Javascript. Is that a major win? Self's prototype-based approach seems quite capable of expressing anything you might want to express with classes, and a few other things besides. (The implementation works by attempting to deduce class structures dynamically, so there's an isomorphism here, of a sort, but the dynamism would make inventing classes on the fly rather inconvenient.) There's a significant difference between Javascript and Self, by the way: a Self object can have multiple `parent' slots, consequently with a form of multiple inheritance, while Javascript is limited to single inheritance (unless you fake it up). However, multiple inheritance is something of a mess, as the original starter of this thread found when he tried to document how to use it. Python's object system certainly isn't ideal. The main problem that I see is that dynamic delegation with `super' is hideously inconvenient to use, which means that programmers will tend towards C++'s static delegation instead. The Python object construction protocol (__new__ and __init__) is somewhat simplistic; constructing instances of multiply inherited classes in general requires a somewhat complicated dance with *args and **kw arguments -- and you lose the ability to reject unknown arguments -- which again leads to programmers taking shortcuts. Most of the rest of the object system seems pretty sound to me. If you have real trouble writing documentation for a feature, it's usually because the feature is badly designed. It might be that it was misunderstood. There seem to be two obvious ways of learning a programming language. One is to try and interpret its concepts in terms of concepts that you already understand. This works, but you end up having to `translate' between the new language; if the translation is imperfect then you'll be confused or frustrated. There's a constant temptation to force one's existing conceptual framework onto the new language -- to use it as if it worked just like something else one is more familiar with that doesn't quite work `right'. The new language is `broken Blub with funny syntax'. The other is to try to understand it on its own terms. This is the harder road that leads to mastery. -- [mdw] -- http://mail.python.org/mailman/listinfo
Re: inverse of a matrix with Fraction entries
casevh cas...@gmail.com writes: I coded a quick matrix inversion function and measured running times using GMPY2 rational and floating point types. For the floating point tests, I used a precision of 1000 bits. With floating point values, the running time grew as n^3. With rational values, the running time grew as n^4*ln(n). Did you clear the denominators before you started? -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Needed: Real-world examples for Python's Cooperative Multiple Inheritance
John Nagle na...@animats.com writes: I'd argue that a better implementation would require that when there's a name clash, you have to specify the class containing the name. In other words, if A is a subclass of B, then B.foo() overrides A.foo(). But if C is a subclass of A and B, and there's an A.foo() and a B.foo(), calling self.foo() in C should be an error, because it's ambiguous. You should have to specify the parent class, using super. How peculiar. `super' is /specifically/ for working out dynamically which superclass to delegate behaviour to, because working it out statically isn't possible in general. The same issue applies in the other direction. If A and B are subclasses of D, and A.foo() and B.foo() are defined, and D calls self.foo(), that's an ambiguity and should be reported. No it isn't. It's downward delegation, which is an essential feature of object oriented design. @This catches the case where two classed both inherit from, say threading.thread, each expecting to have a private thread. Why on earth would anyone do such a bizarre thing? If you want a private thread, then attach one as an attribute. Inheriting is simply madness. Someone then inherits from both classes, getting totally unexpected results when one of the run methods is chosen somewhat arbitrarily. But only because the original design was crazy. If you make a subclass of `thread' it's because you wanted a more specific kind of thread. If you subclass two other subclasses of `thread', it's because you wanted a very specific kind of thread which included the behaviour of those other two subclasses. Detecting a clash requires machinery CPython's lookup machinery currently lacks. What you see as a `clash' is more likely deliberate factoring of behaviour. Again, you seem to think that C++ is, for some reason, the `one true way'. It really isn't. Actually, it's a pretty poor way. But that's not the point: the point is that there are other ways, and if you stopped whining about how Python's object system might theoretically go wrong if you try to use it like it was C++ and started thinking about how to actually make effective use of the features it offers -- features which long predate Python, and have been thought about over many years, in languages such as Zetalisp, Common Lisp, Dylan, Scheme, and variants of Smalltalk -- you might got on much better. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: inverse of a matrix with Fraction entries
Daniel Fetchinson fetchin...@googlemail.com writes: I wouldn't do it that way. Let M be your matrix. Work out the LCM l of the denominators, and multiply the matrix by that to make it an integer matrix N = l M. Then work out the determinant d of that integer matrix. Next, the big step: use Gaussian elimination to find a matrix A (the `adjugate matrix') such that A N = d I. This should be doable entirely using integer arithmetic, and I think without needing any divisions. Finally, we have l A M = d I, so (l/d A) M = I and l/d A is the inverse you seek. Does that make sense? Absolutely! But there is nothing wrong with working out the inverse directly using fractions.Fraction arithmetic, I'd think. It'll work, certainly; but the Fraction implementation will have to do a buttload of GCD computations that it wouldn't need to do if you worked with plain integers. And GCDs are relatively hard, as arithmetical computations go: the usual algorithms require either a number of divisions (which are themselves rather costly) or a bitwise traversal of one of the operands. A million entries seems nontrivial for a matrix, and Gaussian elimination has cubic running time if I remember rightly; I suspect that the transformations I describe would reduce the running time by a fair amount. Of course, I might be drastically underestimating the performance of modern hardware -- I often do -- so this may not be especially relevant. Anyway, the possibility's there. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Needed: Real-world examples for Python's Cooperative Multiple Inheritance
John Nagle na...@animats.com writes: Multiple inheritance in Python is basically what fell out of CPython's internals, not a design. It's one of those areas where order of execution matters, and that wasn't well worked out. I'm not sure about the history, but this doesn't sound right to me. Allowing classes to form a directed acyclic graph isn't very useful. This is simply wrong. It just fell out of the semantics of a naive interpreter. No: there's some essential work needed to make it happen. Originally, the semantics were just wrong. Agreed. Now the awful cases have well-defined semantics, but aren't very useful. Disagree strongly. I think linearization is the only coherent approach to multiple inheritance, and the C3 linearization seems to have almost all of the necessary properties. I'm not quite sure what you mean by `awful' here: the old Python linearization rules were wrong even for very simple graphs (they failed to respect the superclass ordering properly). The CLOS, Dylan and C3 linearizations agree on most commonly occurring class graphs, including many graphs for which the old Python orderings disagreed; the exceptions are where CLOS or Dylan failed to be monotonic or to obey the extended precedence graph. The semantics are extremely useful in the hands of a careful designer. Part of the problem is the notion that if a base class is duplicated in the hierarchy, there's only one copy. This is a problem? No! Duplicating superclass state (as is done in C++ and, I believe, Eiffel) is incoherent. So if you inherit from two classes, both of which inherit from dict, there will be only one dict at the bottom. (I think.) Yes. You end up (probably) with an enhanced dictionary which supports both protocols. This happens frequently, and is very useful. This probably won't do what the authors of any of the classes involved expected. The author of the class which does the multiple inheritance might not even be aware that there's a clash further up in the hierarchy. This is one of those areas where all the code looks right locally, but it's wrong globally. This is only likely if there's a misdesign -- probably using inheritance where containership is required. Best practice for this is don't do it. Some name clashes ought to simply be detected as errors, rather than being given such complex semantics. It sounds like you've been scarred by experiences with C++'s dementedly inadequate object system, with its bizarre `repeated inheritance' rules and hopelessly primitive manual (static!) method combination -- possibly even to the extent of believing that they're in some way `right' or `necessary'. I'm sorry. You have my pity. Python's object system is different, and doesn't have those problems. You probably need a viewpoint shift to be able to think about it properly, but that won't happen if you continue to cling to the idea that C++'s approach is anything like a model of how to do it right. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: inverse of a matrix with Fraction entries
Daniel Fetchinson fetchin...@googlemail.com writes: So after all I might just code the inversion via Gauss elimination myself in a way that can deal with fractions, shouldn't be that hard. I wouldn't do it that way. Let M be your matrix. Work out the LCM l of the denominators, and multiply the matrix by that to make it an integer matrix N = l M. Then work out the determinant d of that integer matrix. Next, the big step: use Gaussian elimination to find a matrix A (the `adjugate matrix') such that A N = d I. This should be doable entirely using integer arithmetic, and I think without needing any divisions. Finally, we have l A M = d I, so (l/d A) M = I and l/d A is the inverse you seek. Does that make sense? -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
Steven D'Aprano steve-remove-t...@cybersource.com.au writes: On Wed, 17 Nov 2010 16:31:40 +, Mark Wooding wrote: But I don't think that's the big problem with this proposal. The real problem is that it completely changes the evaluation rule for the conditional expression. (The evaluation rule is already pretty screwy: Python is consistently left-to-right -- except here.) Not quite... 1+2*3 7 (1+2)*3 9 You're wrong. Python evaluates these left-to-right, as I said. Parentheses override operator associativity; they don't affect evaluation order at all. Consider: def say(x): print 'seen %s' % x return x print say(1) + say(2) * say(3) print (say(1) + say(2)) * say(3) Run this program and you get seen 1 seen 2 seen 3 7 seen 1 seen 2 seen 3 9 So definitely left-to-right. Translating into reverse-Polish, say with Dijkstra's shunting-yard algorithm, is enlightening: you get 1 2 3 * + for the first and 1 2 + 3 * for the second. This preserves evaluation order; indeed, this is a general property of the shunting-yard algorithm. Finally, I quote from the language reference (5.13 of the 2.5 version), just to show that (this time, at least) I'm not trying to impose unfamiliar terminology, and that Python is defined to behave like this and I'm not relying on implementation-specific details. Alas, it also highlights a genuine inconsistency, but one which might be considered tolerable. : 5.13 Evaluation order : = : : Python evaluates expressions from left to right. Notice that while : evaluating an assignment, the right-hand side is evaluated before the : left-hand side. : : In the following lines, expressions will be evaluated in the : arithmetic order of their suffixes: : : expr1, expr2, expr3, expr4 : (expr1, expr2, expr3, expr4) : {expr1: expr2, expr3: expr4} : expr1 + expr2 * (expr3 - expr4) : func(expr1, expr2, *expr3, **expr4) : expr3, expr4 = expr1, expr2 So the above example is /explicitly/ dealt with in the language reference, if only you'd cared to look. Not everything needs to be a one liner. If you need this, do it the old- fashioned way: t = foo() if not pred(t): t = default_value I already explained how to write it as a one-liner: t = (lambda y: y if pred(y) else default_value)(foo()) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Is Unladen Swallow dead?
John Nagle na...@animats.com writes: Python is defined by what a naive interpreter with late binding and dynamic name lookups, like CPython, can easily implement. Simply emulating the semantics of CPython with generated code doesn't help all that much. Indeed. Because you can monkey patch Python objects from outside the class, a local compiler, like a JIT, can't turn name lookups into hard bindings. Nor can it make reliable decisions about the types of objects. But it /can/ make guesses. A dynamic runtime doesn't have to predict everything right in advance; it only has to predict most things sort of well enough, and fix up the things it got wrong before anyone notices. For example, A Python compiler could inline a function call if it makes a note to recompile the calling function if the called function is modified. Most functions aren't redefined, so this is probably a pretty good guess. That adds a sizable performance penalty. Short of global program analysis, the compiler can't tell when code for the hard cases needs to be generated. The right approach is to guess that things are going to be done the easy way, and then detect when the guess is wrong. So the hard-case code, where you figure out at run-time, for ever use of +, whether + is addition or concatenation, has to be generated every time. Making that decision is far slower than doing an add. There's an old trick here called `inline caching'. The first time a function is called, compile it so as to assume that types of things are as you found this time: inline simple methods, and so on. Insert some quick type checks at the top: is this going to work next time? If not, take a trap back into the compiler. The traditional approach is to replace the mispredictions with full dispatches (`monomorphic inline caching'); the clever approach tolerates a few different types, dispatching to optimized code for each (`polymorphic inline caching'), unless there are just too many decision points and you give up. There are time/space tradeoffs to be made here too. Fortunately, you don't have to compile everything super-optimized from the get-go: you can dynamically identify the inner loops which need special attention, and get the compiler to really stare hard at them. The rest of the program might plausibly be left interpreted much of the time for all anyone will care. I've referred to this problem as gratuitous hidden dynamism. Most things which could be changed dynamically in a Python program usually aren't. This is one of the crucial observations for making a dynamic language go fast; the other is that you still have the compiler around if you guessed wrong. An aggressively dynamic runtime has two enormous advantages over batch compilers such as are traditionally used for C: it gets the entire program in one go, and it gets to see the real live data that the program's meant to run against. Given that, I'd expect it to be able to /beat/ a batch compiler in terms of performance. This has been pointed out many times by many people. There's even a PhD thesis on the topic. Without a few restrictions, so that a compiler can at least tell when support for the hard cases is needed, Python cannot be compiled well. This assumes static compilation. It's the wrong approach for a dynamic language like Python. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
Steven D'Aprano st...@remove-this-cybersource.com.au writes: Not everything needs to be a one liner. If you need this, do it the old- fashioned way: t = foo() if not pred(t): t = default_value I already explained how to write it as a one-liner: t = (lambda y: y if pred(y) else default_value)(foo()) I didn't say it couldn't be written as a one-liner. I suggested that it was better not to. Ahh. I misunderstood the first sentence above as dismissing the possibility. Sorry. I agree that it's not a /nice/ one-liner. ;-) The costs of the one-liner are: * reduced readability; * requires an increased level of knowledge of the reader (what's lambda do?); * runtime inefficiency (you create a function object, only to use it once then throw it away). This last can be obviated by a clever compiler (which, in our case, we have not got). The second could be considered an advantage: it's educational! The advantages? * one fewer line of code. In my experience, the obsessiveness in which some people look for one- liners is far from helpful, and goes against the spirit of Python. This isn't Perl :) Oh, I agree completely. On the other hand, it's just /fun/. Python is a fun language and using its features in playfully unusual ways is enjoyable; like a good pun in a natural language. Just as puns aren't always appropriate in written language, playful code isn't always appropriate either; but that doesn't mean it's never appropriate. (Java has no sense of humour. C++ does have, but it's a bit weird.) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Program, Application, and Software
Steven D'Aprano st...@remove-this-cybersource.com.au writes: On Thu, 18 Nov 2010 14:21:47 +, Martin Gregorie wrote: I use 'script' to refer to programs written in languages that don't have a separate compile phase which must be run before the program can be executed. IOW Python and Perl programs are scripts aloing with programs written as awk, Javascript and bash scripts. You're mistaken then about Python, because it does have a separate compilation phase that runs before the program can be executed. Where do you think the .pyc files come from, and what did you think the compile() function did? It just happens automatically, rather than manually. I think Martin meant that there's no /explicit/ compilation phase. As a case in point, tcc is an optimizing native-code compiler for C which is so fast at generating code that it has a mode which accepts an initial `#!' line in its input; the documentation refers to C `scripts'. Awk, Javascript and Perl have full compilation phases too, but they're hidden from the user; bash certainly builds a parse tree but I don't know whether it just walks that or has some other kind of internal representation. Maybe, once upon a time, there was a meaningful distinction to be made between purely interpreted languages and purely compiled languages. No, there never was; only between interpreting and compiling implementations. But today, when interpreted languages have a compilation phase, and compiled languages have the equivalent of eval() and do their compilation at runtime, such a distinction is now fairly arbitrary. Better questions are: * Does the program compile to native machine code or byte code? * How efficient is the machine code, or the virtual machine that executes the byte code? What do you mean by efficient? * Is there an integrated parse-compile-execute cycle, or does the developer have to perform them individually? * To what degree is the syntax of the language aimed at rapid development and/or runtime efficiency? Harder questions to ask, and answer, than Is that language for writing scripts or programs or applications?, but the answers are far more meaningful. Maybe. I note that there are Lisp systems (plural!) which compile to native code (only -- with no interpreter at all), but fully support runtime `eval', batch compilation of source files, aggressive optimization for speed and/or space, and so on. So I think that some of the above questions, at least, present false dichotomies: one doesn't have to choose one or the other; one can have cake and eat it too. Also some of the questions are about the language and some are about the implementation. It's important not to get the two confused. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: how to use socket to get packet which destination ip is not local?
Hans hans...@gmail.com writes: I tried socket bind to 0.0.0.0, but it only binds to any local ip, not any ip which may not be local. therefore the socket cannot get that dhcp offer packet even I can use wireshark to see that packet did come to this pc. You must use a raw socket for this. Raw sockets are fiddly, not very portable, and require privilege. Sorry. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
Christopher nadiasver...@gmail.com writes: i don't like magic names. what about: t = foo() as v if pred(v) else default_value This is an improvement on `it'; anaphorics are useful in their place, but they don't seem to fit well with Python. But I don't think that's the big problem with this proposal. The real problem is that it completely changes the evaluation rule for the conditional expression. (The evaluation rule is already pretty screwy: Python is consistently left-to-right -- except here.) Evaluating a conditional expression starts in the middle, by evaluating the condition. If the condition is true, then it evaluates the consequent (to the left); otherwise it evaluates the alternative (to the right). Screwy, but tolerable. The proposal is to evaluate the /consequent/, stash it somewhere, evaluate the condition, and then either output the consequent which we evaluated earlier or the alternative which we must evaluate now. Of course, the implementation must be able to tell which of these evaluation rules to apply. The marker to look for is either `it' (original anaphoric proposal -- this is the real reason why `it' should be a reserved word: its presence radically alters the evaluation rule, so it ought to be a clear syntactic marker) or `as' (as suggested above). Elsewhere in the language, `as' is pretty consistent in what it does: it provides a name for a thing described elsewhere (a `with' context object, or an imported thing) -- but nothing else. It certainly doesn't suggest a change in the way anything else is evaluated. 1/x if x != 0 else None works for any numeric x; it'd be really surprising to me if 1/x as hunoz if x != 0 else None didn't. -1 on this one. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: simple(?) Python C module question
Mark Crispin nos...@panda.com writes: I have a Python module written in C that interfaces with an external C library. Basically, the project is to make it possible to use that library from Python scripts. If you know who I am, you can guess which library. :) You have your very own Wikipedia page, so others probably needn't guess. However, I now need to write a method that creates what the library calls a stream, and I need method calls to work on that stream. The obvious way to do this in any other OO language is to have an object that holds the stream from the library in an instance variable (which actually will be constant for that object instance), and has various object methods for operating on that stream. Yeah, that's pretty much the way it works in Python, though it's a bit more tedious. (I suppose it's too late to suggest using Cython now. It makes this sort of thing much less unpleasant.) I assume that the object methods are defined by a PyMethodDef table, just as they are for the module. But how do I: [1] define the object You need two things here: a C structure to represent the innards of your custom Python type, and a Python type block (a PyTypeObject) providing everything the Python interpreter needs to know about it. The C structure can be pretty much whatever you like, as long as it begins with the macro PyObject_HEAD: typedef struct thingy { PyObject_HEAD /* your stuff here; maybe: */ stream *s; } thingy; The PyTypeObject is big and boring to fill in but you can probably leave most of it null. The structure is described in the Python API manual, but I think you'll need to fill in: * a name for the type (qualified by your module's name; tp_name); * the object size (sizeof(thingy); tp_basicsize); * a deallocation function (tp_dealloc); * some flags (you probably want Py_TPFLAGS_DEFAULT and maybe Py_TPFLAGS_BASETYPE if you don't mind people making subclasses; tp_flags); * a string to be shown to the user if he asks for help about your type (tp_doc); * a pointer to a methods table (tp_methods); * a pointer to a table of attribute getters and setters (if you want to expose stuff as attributes rather than methods; tp_getset); * an allocator (probably PyType_GenericAlloc; tp_alloc); and * a function to construct a new instance (to be called when Python tries to construct an object by calling the type -- leave it null if you construct instances in some other way; tp_new). You might also want to implement the tp_str function to provide useful information about your object's state (e.g., for debugging scripts). There are some standard protocols which might be useful to implement; it doesn't sound like your streams would benefit from behaving like numbers or sequences, but maybe they might be iterable. You attach methods on the type by mentioning them in the PyMethodDef table you set in tp_methods; they get a pointer to the recipient object (a `thingy' as above) so they can find the underlying stream if they want. Getters and setters are pretty similar, but have a simpler interface because they don't need to mess with argument parsing.. [2] create an instance of the object with the stream and methods If you want Python programs to be able to make streams by saying stream = mumble.stream(...) or whatever then you'll need to implement tp_new: this is pretty much like a standard method, except it gets a pointer to a PyTypeObject to tell it what kind of type to make. (The constructor may be called to construct a subclass of your type.) Parse the arguments and check that they're plausible; then make a new skeleton instance by t = (thingy *)ty-tp_alloc(ty, 0); (where ty is the type pointer you received), fill in your bits, and return (PyObject *)t. Otherwise, well, you go through the same procedure with tp_alloc, only you know which type you want statically. [3] hook the object's destruction to a library stream-close function This is the tp_dealloc function. It should free up any of your resources, and then say obj-ob_type-tp_free(obj); Python will have arranged for this function to exist if you left tp_free as a null pointer. Python does NOT need to look at the stream in any way. Ideally, the object is just a blob that only has method calls. That's what you get anyway, if you use the C API. If you want Python programs to be able to poke about inside your objects, you have to let them explicitly, and that means writing code. This ought to be simple, and not even require me to know much Python since basically the task is just this module and a few very basic Python scripts to use it. Other people will be writing the real scripts. It doesn't require you to know any Python at all. It /does/ require a certain familiarity with the implementation, though. Of course, I could just have the open method return the stream pointer as a big
Re: Program, Application, and Software
Alexander Kapps alex.ka...@web.de writes: Application: Usually a large(er), complex program I'd say that an `application' is specifically a program intended for direct human use. Other things are servers, daemons and utilities. But I might just be weird. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: strange behavor....
Steven D'Aprano st...@remove-this-cybersource.com.au writes: def foo(): l = [] for i in xrange(10): (lambda j: l.append((lambda: i, lambda: j)))(i) print [(f(), g()) for f, g in l] Here's a slightly less condensed version that demonstrates the same behaviour, but may be slightly easier to understand: The output is the same but the reasons for it are different: def spam(): a = [] b = [] for i in xrange(5): a.append(lambda: i) b.append(lambda i=i: i) Here, you've replaced lambda-binding by a default argument value. print [f() for f in a] print [f() for f in b] In your function foo, the name i is bound to the objects 0, 1, 2, ... 9 sequentially, each time around the for-loop. Inside the loop, a function object is created and then called: (lambda j: l.append((lambda: i, lambda: j)))(i) (Aside: this depends on scoping rules that were introduced quite late in Python's history -- prior to version 2.2, this wouldn't work at all.) Indeed. The default-argument trick above was used to simulate it. Not coincidentally, it was around version 2.2 that Python became interesting to me... The outer lambda: lambda j: l.append(...) has a name in the function namespace (a local variable) called j. On entry to this function, this j is bound to the same object which is bound to i *at the time that the function is called*. That is, each of the sequence of outer lambdas get a distinct j = 0, 1, 2, ... Ahh. You've invented a new concept of localness instead, which is equivalent to the usual notion of binding. None of the function A0, A1, A2, ... have any local variable i. i.e., i is free in the An functions and in the outer lambda... Functions B0, B1, B2, ... similarly have no local variable j. When you call any of the Bs, Python looks in the enclosing scopes for a variable j. However, in this case it *does* find one, in the outer lambda, ... but j is bound in the outer lambda. This is not new terminology: it goes back to lambda calculus: a variable x occurs free in a term T if * T is x; * T is U V where x occurs free in U or V; or * T is lambda y.U where y is not x and x occurs free in U. If x occurs free in T then it occurs bound in lambda x.T. See also SICP. * Python's `for' loop works by assignment. The name `i' remains bound to the same storage location throughout; This is not necessarily true. It's true for CPython, where function locals are implemented as fixed slots in the function object; since the slot doesn't move relative to the function, and the function doesn't move relative to the heap, the name i is in a fixed storage location for the life of foo. But that's not necessarily the case for all implementations -- locals could be stored in a data structure that moves data around (say, a red-black tree), or objects could be free to move in the heap, or both. Don't be silly. In a tree, the `location' would be the tree node containing the corresponding key. You're working at the wrong level of abstraction. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: strange behavor....
Arnaud Delobelle arno...@gmail.com writes: exec a=2 in d assigning 2 to 'a' d['a'] 2 exec global a; a = 3 in d d['a'] 3 Oooh, now isn't that an interesting wrinkle? I've been careful (without drawing attention) to restrict my arguments to variables inside functions, largely because Python's global scopes work completely differently. (Python's global scopes work similarly to traditional Lisp and Scheme, which isn't at all objectionable, but it's not the only way of managing global scopes. Queinnec's Lisp In Small Pieces describes others.) So even if the globals() dictionary is custom, its __setitem__ method is *not* called. Fascinating. Thank you. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
Dmitry Groshev lambdadmi...@gmail.com writes: First of all: how many times do you write something like t = foo() t = t if pred(t) else default_value ? Of course we can write it as t = foo() if pred(foo()) else default_value but here we have 2 foo() calls instead of one. Why can't we write just something like this: t = foo() if pred(it) else default_value where it means foo() value? How about t = (lambda y: y if pred(y) else default_value)(foo(x)) You could even package the lambda into a named function if you get bored of typing or your aesthetic senses are offended. And the third. The more I use python the more I see how natural it can be. By natural I mean the statements like this: [x.strip() for x in reversed(foo)] which looks almost like a natural language. But there is some pitfalls: if x in range(a, b): #wrong! it feels so natural to check it that way, but we have to write if a = x = b This, I think, is your error. The test `x in range(a, b)' means the same as `a = x b' (only in Python 2 it builds a list and then throws it away again). Such half-open intervals turn out to be what you want most of the time, and I think you'll avoid many bugs if you embrace them rather than trying to cling to the fully-closed intervals above. Python very definitely made the right decision to use half-open intervals pervasively, e.g., for `rangeand 'in sequence slicing. It's a bad idea to fight against it. Advantages of half-open intervals [a, b): * The number of elements is exactly b - a; closed intervals contain an extra element which is often forgotten. * They compose and split nicely: if a = c = b then [a, b) is exactly the disjoint union of [a, c) and [c, b). * Sums over these intervals are often better behaved; indeed, there's a rather pretty analogy between sums on half-open intervals and definite integrals which is lost if you use closed intervals. (The above two observations are special cases of this one.) See Concrete Mathematics (Graham, Knuth, Patashnik) for more on this. * It's easy to express an empty interval. You can't do that if you work entirely with closed intervals, but empty sets are an important boundary case and it's annoying to have to handle them separately. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: strange behavor....
Tracubik affdfsdfds...@b.com writes: def change_integer(int_value): ... int_value = 10 ... ... def change_list(list): ... list[0] = 10 [...] why the integer value doesn't change while the list value do? Because in the first case you changed a variable local to the function, and that variable was lost when the function returned; and in the second case, you modified the list value that was passed to the function. in Pascal i can choose the behavour of parametres, how this work on Python? You must learn to distinguish two notions to understand how this works in Python: the notions are /assigning a value to a variable/, and /mutating a value/. The former is what simple assignment `foo = ...' does: it makes the variable store a different value. Assigning a value to a function argument /never/ affects the caller in Python. It's simply not possible to write a `swap' function in Python. The latter means that a value itself changes but the relevant variables continue to store the same values. Alas, Python is actually slightly confusing here, since the same notation `=' sometimes means assignment and sometimes means mutation. You can tell which is which by looking at the left hand side: if it's a simple variable name, the variable is assigned a new value; if it's something more complicated (e.g., indexing (`foo[0]'), or attribute selection (`foo.bar') then some mutation is (probably) going to happen: these kinds of assignment are translated into method calls, so what actually happens is up to the object in question. It gets worse: compound assignment -- statements like `foo += ...' -- might either be mutation or assignment. What happens if the current value of `foo' has the an appropriate method is that the method is called, and probably mutates the value of foo; otherwise Python treats the statement as if it had been `foo = foo + (...)'. Returning, sort of, to the point: if you want to write a function which causes side-effects on its caller, then you have[1] to do it by mutating the caller's argument values. So you could write an awful `swap' function like def awful_swap(x, y): x[0], y[0] = y[0], x[0] and then you have to call it as xx = [x] yy = [y] awful_swap(xx, yy) x = xx[0] y = yy[0] but there's no good reason to actually do such a thing in Python when you can write x, y = y, x anyway. In Pascal, one tends to use `var' parameters to work around the fact that Pascal functions can only return a single value. This is true in Python too, but it isn't anywhere near as annoying because Python makes it easy (a) to combine multiple values together into a tuple (`return x, y, z') and (b) to pick tuples apart into their components again at the other end (`a, b, c = some_function()'). If you have a number of values which you find that you're combining and splitting apart repeatedly then maybe you're better off putting them together in a class with some appropriate operations. [1] In general; if the called function happens to be lexically enclosed in its caller, then it can play with its caller's variables directly -- well, in Python 3, anyway. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: strange behavor....
Terry Reedy tjre...@udel.edu writes: On 11/13/2010 11:29 AM, Mark Wooding wrote: Alas, Python is actually slightly confusing here, since the same notation `=' sometimes means assignment and sometimes means mutation. I disagree somewhat. An object is mutated by an internal assignment. Some object types are primitive, provided by the runtime system; there are no `internal' variables to be assigned in these cases. (It is possible in principle in Python 3 to implement all of the compound data types using only assignment and closures.) ll[0] = 1 assigns 1 to the 0 slot of ll. o.a = 1 assigns 1 to the 'a' attribute of o. This which might be implemented by assigning 1 to the 'a' slot of o.__dict__, just as a=1 might be implemented by assigning 1 to the 'a' slot of a namespace dict. There's a qualitative difference here: simple assignment has semantics defined by the language and provided by the implementation, and can therefore be understood in isolation, using only lexically apparent information; whereas the complex assignments are implemented by invoking methods on the objects mentioned on the left hand side. The objects in question may choose not to implement some other semantics, so the runtime behaviour might not be determinable even in principle without actually executing the program. (Compound assignment has the same problem writ large.) Assignment *always* binds an object to a target. No! Assignment /never/ binds. There is syntactic confusion here too, since Python interprets a simple assignment in a function body -- in the absence of a declaration such as `global' to the contrary -- as indicating that the variable in question should be bound to a fresh variable on entry to the function. But assignment itself doesn't perform binding. (This is a persistent error in the Python community; or, less charitably, the Python community gratuitously uses the word in a different sense from the wider programming-language-theory community. See Lisp literature passim, for example.) There's a two step mapping: names - storage locations - values. Binding affects the left hand part of the mapping; assignment affects the right hand part. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: strange behavor....
Dave Angel da...@ieee.org writes: No, an (=) assignment is always an assignment. No. In `foo[0] = bar' it's a method call in disguise. It changes the item on the left hand side to refer to a new object. Not necessarily. It could do anything at all depending on the type of the recipient object. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: strange behavor....
Arnaud Delobelle arno...@gmail.com writes: m...@distorted.org.uk (Mark Wooding) writes: Assignment /never/ binds. There is syntactic confusion here too, since Python interprets a simple assignment in a function body -- in the absence of a declaration such as `global' to the contrary -- as indicating that the variable in question should be bound to a fresh variable on entry to the function. But assignment itself doesn't perform binding. (This is a persistent error in the Python community; or, less charitably, the Python community gratuitously uses the word in a different sense from the wider programming-language-theory community. See Lisp literature passim, for example.) There's a two step mapping: names - storage locations - values. Binding affects the left hand part of the mapping; assignment affects the right hand part. I'm not sure the notion of storage location is useful in Python. We'll see. I think I understand Python programs correctly using only the notions of name and value (or object). Challenge: explain the following code using only those concepts. def foo(): l = [] for i in xrange(10): (lambda j: l.append((lambda: i, lambda: j)))(i) print [(f(), g()) for f, g in l] I explain this as follows. * Python's `for' loop works by assignment. The name `i' remains bound to the same storage location throughout; this binding is established on entry to the function. Since `i' is not rebound in any function lexically enclosed in `foo', every occurrence of `lambda: i' refers to this same storage location. At the end of the loop, this storage location contains the value 9. * The name `j' is rebound repeatedly: in each iteration of the `for' loop, the function `lambda j: ...' is invoked, binding `j' to a fresh storage location into which the value of `i' at the time is stored. Since the function `lambda: j' is lexically enclosed within this function, the name `j' refers to a different storage location in each of these functions, these storage locations are initialized with distinct values 0 up to 9, and they are never changed. * Therefore each `lambda: i' function, when called after the loop, outputs the same value 9; and each `lambda: j' function, when called after the loop, outputs a distinct value. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: strange behavor....
Steven D'Aprano st...@remove-this-cybersource.com.au writes: On Sat, 13 Nov 2010 20:01:42 +, Mark Wooding wrote: Some object types are primitive, provided by the runtime system; there are no `internal' variables to be assigned in these cases. You seem to be making up your own terminology here, or at least using terminology that isn't normally used in the languages I'm used to. I was attempting to define possibly unfamiliar terms as I went along. Did you not notice? If you mean primitive in the sense of built-in, your conclusion is wrong. Such primitive types include dicts and lists, Yes, those are precisely the ones I was thinking of. which are sophisticated container objects with internal variables to be assigned to: They have internal state. I don't think that internal state consists of (Python) variables, though. This is why I brought up the possibility of a pure Python implementation, maintaining its state by assigning to variables captured using closures. There's a qualitative difference here: simple assignment has semantics defined by the language and provided by the implementation, and can therefore be understood in isolation, using only lexically apparent information; whereas the complex assignments are implemented by invoking methods on the objects mentioned on the left hand side. Again, you're using unfamiliar terminology. I'm sorry. I thought I defined those terms recently. (It appears not. Sorry.) I meant to refer to assignments in which the target is an identifier (to use the actual terminology from the manual). Simple and complex assignment -- I can guess you mean name binding = simple and any other reference binding = complex in Python terminology: Again: assignment is not binding. See the explanation below. The thing is, the semantics of assigning to built-in components are equally defined by the language as the semantics of name binding. Did you read what I said? You are right to point out that for arbitrary types: x[2] = 5 need not be an assignment, Good. This was /precisely/ what I was pointing out: determining /whether/ the value named by an identifier inhabits one of the built-in types is, in general, hard. The distinction between the two count as an important proviso to the discussion: x[2] = 5 is only an assignment if the type of x is non-pathological and not broken. The latter is not an assignment: it's a disguised method call. But putting aside such pathological cases, I don't think you can justify distinguishing between simple and complex assignment. To conflate them is to confuse two different levels of meaning. Simple assignments occur because the language is hard-wired that way; complex assignments are disguised method calls which often mutate values. Names are only one type of reference in Python, not the only one, and assignments other than name-binding can be fully understood from the language semantics *provided you know the type is a built-in*. Assignment *always* binds an object to a target. No! Assignment /never/ binds. A shocking claim that requires more explanation. If it doesn't bind, what does it do? Duh! It assigns. You're not usually this slow. Fortunately I explain below. There is syntactic confusion here too, since Python interprets a simple assignment in a function body -- in the absence of a declaration such as `global' to the contrary -- as indicating that the variable in question should be bound to a fresh variable on entry to the function. Well, there seems to be some confusion here, but I don't think it's ours... local variables in functions aren't bound on *entry* to the function. How could they be? They are bound *when the assignment is executed*, which may be never -- hence it is possible to get an UnboundLocalError exception, if you try to retrieve the value of a local which hasn't yet had a value bound to it. The exception name perpetuates the misunderstanding, alas; but it's traditional, from Lisp, to say that a variable is `unbound' if it contains no value. But assignment itself doesn't perform binding. (This is a persistent error in the Python community; or, less charitably, the Python community gratuitously uses the word in a different sense from the wider programming-language-theory community. See Lisp literature passim, for example.) *Less* charitably? I'm sorry, you think that being *wrong* is better than being *different*? That's not a moral judgment I can agree with. Being wrong is perhaps justifiable, and is rectifiable by learning. Being gratuitously different in such a case is to intentionally do a disservice to those coming from or going to other communities where they encounter more conventional uses for the terms in question. There's a two step mapping: names - storage locations - values. Binding affects the left hand part of the mapping; assignment affects the right hand part. That gratuitously
Re: strange behavor....
Dennis Lee Bieber wlfr...@ix.netcom.com writes: def swapFunc(a, b): return b, a That's not what a `swap' function should do. Alas, Python is actually slightly confusing here, since the same notation `=' sometimes means assignment and sometimes means mutation. = means just one thing, a rebinding of some identifier to a different object. Names aren't bound to objects. See elsewhere. Or, in more general, = rebinds the fully qualified name to a different object, which has the result of mutating a partially qualified name (a name whose suffix has be removed). Names aren't mutated at all. Values (or, synonymously, objects) are mutated. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: strange behavor....
Steven D'Aprano st...@remove-this-cybersource.com.au writes: On Sat, 13 Nov 2010 21:42:03 +, Mark Wooding wrote: Dave Angel da...@ieee.org writes: No, an (=) assignment is always an assignment. No. In `foo[0] = bar' it's a method call in disguise. How does that imply that can't also be an assignment? Is `splat(34)' an assignment? If so, I think the term's meaning is grievously diluted. I'd rather say that `splat(34)' might mutate a value, or have side effects, and reserve the term `assignment' for the job of explaining how variables work. That seems pretty tricky, because we're arguing about it a lot, so I think we need sharply defined concepts so that we don't get more confused than we have to be. Of course, you're correct that it's not *necessarily* an assignment, [...] I don't think it helps to overload newbies struggling with the basics with such pathological cases though. I think that we're better off giving `newbies' a conceptual framework which is robust, so that they can understand pathological situations when they occur. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: How to test if a module exists?
r0g aioe@technicalbloke.com writes: Really? I get a metric butt-ton of spam every day to this address. I'm sure I get sent a lot of spam (though I don't know for sure -- see below). But I don't think much of it comes from Usenet harvesters any more. Right now it simply filtered by address straight into my recycle bin, I suppose if it ever becomes burdensome or starts to choke my bandwidth I'll tell my mailserver to bounce it :) Don't do that. Get your mailserver to /reject/ spam during SMTP with a 5xx code. Bouncing spam is really bad because it implicitly assumes that the envelope sender address is good. Spam rarely has a valid envelope sender. If you're lucky, the envelope sender is simply invalid, and you'll end up with a double-bounce when your mailserver finds out. If you're unlucky, the envelope sender is a /valid/ address from the spammer's list and some innocent victim will end up receiving your bounce (this is called `backscatter'). -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: How to test if a module exists?
Lawrence D'Oliveiro l...@geek-central.gen.new_zealand writes: In message mailman.894.1289510633.2218.python-l...@python.org, MRAB wrote: ... the next one at 3 Nov 2010 22:40 Re: Allowing comments after the line continuation backslash and _all_ the subsequent ones arrived with an _unobfuscated_ email address. You mean from this one on http://mail.python.org/pipermail/python-list/2010-November/1259515.html? No. More like http://article.gmane.org/gmane.comp.python.general/677953 We'll accept your apologies now. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: How to test if a module exists?
r0g aioe@technicalbloke.com writes: You use your main address on USENET rather than a junk one!? Obfuscated or not that's either brave or foolhardy! I use my real email address. I also have an aggressive spam filter. But I don't think that much of my comes from Usenet harvesters any more, to be honest. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Am I The Only One Who Keeps Reading ?Numpy? as ?Numpty??
Lou Pecora pec...@anvil.nrl.navy.mil writes: Bigger question: How do you pronouce it? Rhymes with `grumpy'. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: subclassing str
Lawrence D'Oliveiro l...@geek-central.gen.new_zealand writes: In message 87lj52kwln.fsf@metalzone.distorted.org.uk, Mark Wooding wrote: One option is to implement a subclass which implements the additional protocol. This is why I think object orientation ruins your ability to think properly. For “protocol” read “function”. If you want to implement a new function, then implement a new function, why do you have to go through this “subclassing” malarkey just to do something so simple. Functions don't do type-dependent dispatch, which was, of course, the whole point. A `protocol' is a collection of messages understood by a number of different kinds of objects, causing potentially object-specific behaviour. I gave the explicit example of serialization: string probably serializes differently from an integer or a list. The `__str__' and `__repr__' methods form a simple protocol for object printing, as an additional example. The `str' and `repr' functions provides a potentially useful external entry points into the protocol, but they work by doing a type-dependent dispatch on the argument -- calling the appropriate method. Object orientation isn't useless or an impediment to clear thinking. It does seem to have turned into a bizarre kind of religion by some, and many `mainstream' languages provide very poor object orientation features (yes, Java and C#, I'm looking at you). But OO can be useful. I think the notion of `protocol' is central to coherent OO design, but this seems largely overlooked in much of the literature I've read. This may mean that many people are muddled about what OO is actually for. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Allowing comments after the line continuation backslash
Lawrence D'Oliveiro l...@geek-central.gen.new_zealand writes: In message 878w12kt5x.fsf@metalzone.distorted.org.uk, Mark Wooding wrote: 2. The MainWindow class only has the `Window' attribute described in its definition. Apparently there are other attributes as well (the ColorMumbleList family for one, also `LayerDisplay'). Similarly, the LoadedImage class has attributes `Contents' and `FileName', but I see attributes `RowStride', `ImageDrawSize' and `SrcDimensions' used immediately below. These are really just namespaces, one for the GUI context and the other for the image data. I think my point was about the rather selective documentation of the namespaces. The trivial-class trick is something I use myself (though usually to simulate a structure rather than just to carve up namespace) so I don't find it objectionable in and of itself. 3. In SelectSaveMenu, there's a curious `for' loop: for State in (gtk.STATE_NORMAL,) : # no need for gtk.STATE_INSENSITIVE ## blah Firstly, this is obviously equivalent to `state = gtk.STATE_NORMAL' followed by the loop body (YAGNI). It’s a tuple of one element. It used to be a tuple of two, and there is the possibility it might need to become that again (as intimated at in the attached comment). That’s why it stays a tuple. I guessed the history. I'm in two minds about this sort of thing. I /like/ history: I'm fascinated by the history of old programs and programming languages; but looping over a single thing just seems weird. Of course, being boilerplate, the similarities visually outweigh the differences, when in fact it's the differences that are interesting. That is generally how code reuse works. All the “boilerplate” is in the function definition, so I just have to call it parameterized by the differences appropriate to each instance. Except that's not the case. There are extremely close similarities between the six calls which strongly suggest (to me, anyway) that further factoring would be beneficial. I detest writing anything more than once, and don't much enjoy playing spot-the-difference when reading code. The six calls are a screenful of spot-the-difference. It doesn't help that all of the names of the things involved are so wretchedly verbose. Oh please, no. Since when are explanatory names “wretchedly verbose”? When the start and end bits are the same and the different bits are hidden in the middle. After staring at a screenful of MainWindow.MumbleDisplay my head starts spinning. How about the following? def make_listview_l1 ... And what, pray tell, is the significance of the name “make_listview_l1”? If there is something I would describe as “wretched”, it is the use of random numerical suffixes like this. It's a terse reference to List1Box (your name). Since it was only being used in the following two lines, I figured the name didn't matter much. (In Lisp, I'd have wrapped the two lines in FLET and simply called the function FROB.) Looking at some of the rest of the code, it might (or might not) be worthwhile actually making a class to gather together a list's model and view; subclasses can then vary their individual parameters, and the various colour lists can also keep the various captions with them. Most of that variation is already handled without the limitations of thinking in classes. For example, selection of a colour in all three lists is handled through a single EditColor routine. And of course you’ve already seen how a single DefineScrollingList routine can be used to set up all the scrolling lists used in this GUI. There's so much commonality in the arguments that I'm not convinced that they're fully factored. Worse, there are several tables involving your various ColorMumbleLists: adding another would require fiddling with all of them, which suggests that things have been sliced up the wrong way. (I'm aware in this instance that the set of such things is externally constrained in this case.) Maybe packaging all of the information about each individual list in one object and having a list of these objects would be better. 5. Much of the indentation and layout is rather unconventional, though not intolerable. But I found (deep in `SelectSaveMenu'): NewRenderPixels = array.array \ ( B, FillColor * (ImageRowStride // 4 * ImageBounds[1]) ) to be most disconcerting. Is the structure of the expression not apparent to you? No, it really isn't. Oddly enough, I'd find (setf new-render-pixels (array:array B (* fill-color (floor image-row-stride 4) (aref
Re: How to test if a module exists?
Lawrence D'Oliveiro l...@geek-central.gen.new_zealand writes: I see that you published my unobfuscated e-mail address on USENET for all to see. I obfuscated it for a reason, to keep the spammers away. I'm assuming this was a momentary lapse of judgement, for which I expect an apology. Otherwise, it becomes grounds for an abuse complaint to your ISP. Don't be silly! If anything, using forged email addresses in Usenet headers is closer to abuse. Note that there's nothing to stop `new_zealand' from becoming a TLD at some point (the underscore makes it unlikely, I grant). If you'd mangled the local part, or used an explicitly reserved TLD such as `example', then there wouldn't be a problem. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Pythonic/idiomatic?
Seebs usenet-nos...@seebs.net writes: ' '.join([x for x in target_cflags.split() if re.match('^-[DIiU]', x)]) This appears to do the same thing, but is it an idiomatic use of list comprehensions, or should I be breaking it out into more bits? It looks OK to me. You say (elsewhere in the thread) that you're stuck with 2.4 compatibility. I'd personally avoid the regexp, though, and write this (actually tested with Python 2.4!): ' '.join(i for i in target_cflags.split() for p in 'DIiU' if i.startswith('-' + p)) You will note that of course, I have carefully made it a one-liner so I don't have to worry about indentation*. I failed at that. You have to put up with my indentation. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Compare source code
Arnaud Delobelle arno...@gmail.com writes: python-mode has python-beginning-of-block (C-c C-u) and python-end-of-block. Yes. It was one of my explicit gripes that editing Python requires one to learn entirely new and unfamiliar keystrokes for doing fairly familiar editing tasks. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: functions, list, default parameters
Lawrence D'Oliveiro l...@geek-central.gen.new_zealand writes: In message mailman.608.129032.2218.python-l...@python.org, Robert Kern wrote: So examining LHS selectors is not sufficient for determining immutability. Yes it is. All your attempts at counterexamples showed is that it is not necessary, not that it is not sufficient. You've got them the wrong way around. A is sufficient for B if and only if B is true whenever A is true; i.e., it is never the case that A is true and B is false. In this case, we also say that B is necessary for A. See also http://en.wikipedia.org/wiki/Necessary_and_sufficient_condition -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Silly newbie question - Caret character (^)
Philip Semanchuk phi...@semanchuk.com writes: What's funny is that I went looking for a printed copy of the C standard a few years back and the advice I got was that the cheapest route was to find a used copy of Schildt's Annotated ANSI C Standard and ignore the annotations. So it serves at least one useful purpose. The book was much cheaper than a copy of the C standard from ANSI or ISO even when it was new. It was a common joke (HHOS) at the time that the difference in price reflected the value of the annotations. (It also has two errors in the actual text of the standard. There's a character missing in the syntax summary, and one page was omitted entirely, replaced by a copy of the previous page: my copy came with a corrected page ineptly glued in at the relevant place.) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: subclassing str
rantingrick rantingr...@gmail.com writes: One thing i love about Python is the fact that it can please almost all the religious paradigm zealots with it's multiple choice approach to programming. However some of the features that OOP fundamentalists hold dear in their heart are not always achievable in a clean manner with Python. Yes you could use a function but that is not the OOP way. It can be more than just an aesthetic difference. Sometimes it can be nice to extend existing classes to understand additional protocols. For example, suppose you're implementing some object serialization format: it'd be really nice if you could add `serialize' methods to `str', `int', `list' and friends. This is certainly the Smalltalk way. Unfortunately, you can't do it in Python. One option is to implement a subclass which implements the additional protocol. This causes fragmentation: now each protocol wants its own subclass: if you want an object which understands both protocols, you need to mess with multiple inheritance[1] (and, in Python, at least, hope that everyone is using `super' properly to implement upwards delegation). Otherwise you have to do the dispatch yourself, either by hand or by using one of the generic function/multimethod frameworks. [1] At least Python gives you a fighting chance of getting this to work. Java and C# won't countenance multiple inheritance at all, and C++ will botch it all by giving you a separate copy of the common superclass's state for each protocol implementation (what are the chances that everyone decided to use a virtual base class?) /and/ hideously breaking upwards delegation. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: populating a doubly-subscripted array
Gregory Ewing greg.ew...@canterbury.ac.nz writes: A reasonably elegant way to fix this is to use list comprehensions for all except the innermost list: ff = [[0.0]*5 for i in xrange(5)] Yes, this is a good approach. I should have suggested something like this as a solution myself, rather than merely explaining the problem. If you're computing heavily with arrays, you might also consider using numpy arrays instead of lists. Also a good idea. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Allowing comments after the line continuation backslash
Lawrence D'Oliveiro l...@geek-central.gen.new_zealand writes: In message 87fwvdb69k.fsf@metalzone.distorted.org.uk, Mark Wooding wrote: for descr, attr, colours in [ ('normal', 'image','Normal'), ('highlighted', 'highlight','Highlighted'), ('selected','select', 'Selected')]: colourlist = getattr(MainWindow, 'Colors%sList' % colours) ## ... But then you lose the ability to match up the bracketing symbols. You're right. I do. That’s why I put them on lines by themselves. But the bracketing symbols are thoroughly uninteresting! All that putting them on their own lines achieves is to draw attention to the scaffolding at the expense of the building. It's great if you like the Pompidou Centre, I suppose... Besides, any editor worth its salt will highlight bracket mismatches for the reader, or at least get its automatic indentation in a twist if you get the brackets wrong. Maybe you should look at the code in context https://github.com/ldo/dvd_menu_animator, then you can express some more opinions on how to improve it. 1. class keyval: `are there official symbolic names for these anywhere?' The gtk.keysyms module contains `Return', `KP_Enter', `Left', `Up', `Right', and `Down'. Question: why are `returnkey' and `enterkey' defined in hex and the others in decimal? 2. The MainWindow class only has the `Window' attribute described in its definition. Apparently there are other attributes as well (the ColorMumbleList family for one, also `LayerDisplay'). Similarly, the LoadedImage class has attributes `Contents' and `FileName', but I see attributes `RowStride', `ImageDrawSize' and `SrcDimensions' used immediately below. 3. In SelectSaveMenu, there's a curious `for' loop: for State in (gtk.STATE_NORMAL,) : # no need for gtk.STATE_INSENSITIVE ## blah Firstly, this is obviously equivalent to `state = gtk.STATE_NORMAL' followed by the loop body (YAGNI). Secondly, the loop is followed by an `#end if' comment. If you're going to write the things, at least get them right! 4. Ahh! I've tracked down where the MainWindow is actually populated. Ugh. The code appears to revel in boilerplate. (For those at home, we're now looking at `SetupMainWindow', specifically at the calls to `DefineScrollingList'.) I count six calls, each nearly (but not quite) identical, of about eleven lines each. Of course, being boilerplate, the similarities visually outweigh the differences, when in fact it's the differences that are interesting. It doesn't help that all of the names of the things involved are so wretchedly verbose. How about the following? def make_listview(label, render, colattr, head, bounds, osc, box): setattr(MainWindow, label + 'Display', DefineScrollingList(getattr(MainWindow, label + 'List'), 0, render, colattr, head, bounds, osc, box) def make_listview_l1(label, head, osc): make_listview(label, None, 'text, head, (160, 160), osc, List1Box) make_listview_l1('Button', 'Buttons', None) make_listview_l1('Layer', 'Button Layer', LayerSelectionChanged) MainWindow.colourlist = {} MainWindow.colourview = {} for head in ['Normal', 'Highlight', 'Select']: MainWindow.colourlist[head] = gtk.ListStore(gobject.TYPE_PYOBJECT) MainWindow.colourview[head] = \ DefineScrollingList(MainWindow.colourlist[head], 0, ColorCellRenderer(), None, head, (120, 120), None, List2Box) make_listview('LoadedColors', ColorCellRenderer(), None, '', (120, 240), None, MiddleBox) Looking at some of the rest of the code, it might (or might not) be worthwhile actually making a class to gather together a list's model and view; subclasses can then vary their individual parameters, and the various colour lists can also keep the various captions with them. (Sometimes a strong separation between model and view is a good thing; this doesn't seem to be one of those times.) 5. Much of the indentation and layout is rather unconventional, though not intolerable. But I found (deep in `SelectSaveMenu'): NewRenderPixels = array.array \ ( B, FillColor * (ImageRowStride // 4 * ImageBounds[1]) ) to be most disconcerting. Also, I couldn't work out why some parens are indented only two spaces and others are indented the full eight. Oh! It's inconsistent tab/space selection. I'm afraid that about this point I had to get on with some other stuff. I've done enough throwing
Re: Allowing comments after the line continuation backslash
Tim Chase python.l...@tim.thechases.com writes: On 11/09/10 18:05, Robert Kern wrote: For me, putting the brackets on their own lines (and using a trailing comma) has little to do with increasing readability. It's for making editing easier. It also makes diff's much easier to read (my big impetus for doing the same as Robert) Hmm. That's a good point, actually. I'm not overly fussed about the ease of editing: it doesn't seem especially hard either way. But nice diffs are definitely valuable. Food for thought; thanks. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Popen Question
Lawrence D'Oliveiro l...@geek-central.gen.new_zealand writes: In message ib0kor01...@news5.newsguy.com, Chris Torek wrote: ['/bin/sh', '-c', 'echo', '$MYVAR'] (with arguments expressed as a Python list). /bin/sh takes the string after '-c' as a command, and the remaining argument(s) if any are assigned to positional parameters ($0, $1, etc). Doesn’t work. What doesn't work? You were being given an explanation, not a solution. I don’t know what happens to the extra arguments, but they just seem to be ignored if -c is specified. The argument to -c is taken as a shell script; the remaining arguments are made available as positional parameters to the script as usual (only starting with $0 rather than $1, for some unknown reason). -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: populating a doubly-subscripted array
g...@accutrol.com writes: What am I missing? I am using Python 3.1.2. ff = [[0.0]*5]*5 ff#(lists 5x5 array of 0.0) for i in range(5): for j in range(3): ff[i][j] = i*10+j print (i,j,ff[i][j]) # correctly prints ff array values ff# try this and see what happens! result of third print of ff [[40, 41, 42, 0.0, 0.0], [40, 41, 42, 0.0, 0.0], [40, 41, 42, 0.0, 0.0], [40, 41, 42, 0.0, 0.0], [40, 41, 42, 0.0, 0.0]] Obviously there is something missing in my understanding of how array values are populated. Why do all rows get populated with the same set of values (40, 41, 42)? [I suppose that the trailing 0.0 entries aren't in question: they're because the individual rows have width 5 -- from `[0.0]*5' -- but only the first three items of each is initialzed -- because j iterates only over range(3).] So, why do they all come out the same? The answer is because in fact there are only two lists involved. You probably thought that you were building something like the thing on the left. In fact, you have the thing on the right. (Try to forgive the rubbish ASCII art.) .--..--.--.--.--.--..--. | -| | | | | || --. |__|`--^--^--^--^--'|__| \ | |.--.--.--.--.--.| | \ | -| | | | | || ---. \ |__|`--^--^--^--^--'|__| \v | |.--.--.--.--.--.| | \.--.--.--.--.--. | -| | | | | || -| | | | | | |__|`--^--^--^--^--'|__| /`--^--^--^--^--' | |.--.--.--.--.--.| | / ^ | -| | | | | || --' / |__|`--^--^--^--^--'|__| / | |.--.--.--.--.--.| | / | -| | | | | || --' `--'`--^--^--^--^--'`--' What [x] * n does is make a list, whose length is n, and all of whose entries are precisely the value x. If x itself is a list, then you get an outer list all of whose entries are the /same/ inner list -- not copies of it. So when you appear to change entries in one of the inner lists, all the other inner lists seem to change too -- because they're actually the same list. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Compare source code
Lawrence D'Oliveiro l...@geek-central.gen.new_zealand writes: I would never do that. “Conserving vertical space” seems a stupid reason for doing it. Vertical space is a limiting factor on how much code one can see at a time. I use old-fashioned CRT monitors with 4x3 aspect ratios and dizzyingly high resolution; I usually work with two columns of code, but can get four if I give up on things like xterms. I still find it rather limiting: I have to remember everything which won't fit on the screen. I've no idea how people manage with these ridiculous widescreen monitors. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Silly newbie question - Carrot character (^)
Nobody nob...@nowhere.com writes: You're taking how too literally, so let me rephrase that: A reference manual tells you what you need to know in order to use the language. A specification tells you what you need to know in order to implement it. I still don't see those as being different. A language reference should set out all of the details of the language syntax and semantics. It should answer every question of the form `what happens if I write this?' In so doing, it /must/ also provide enough information for an implementer to write an new implementation. A tutorial provides an overview of the language, but won't necessarily describe every aspect (maybe not even close), and is generally designed to be read in order. Agreed. A reference manual would describe whatever you need to know in order to use the language. It shouldn't omit anything short of the you are not expected to understand this level. IOW, any omissions shouldn't matter unless you are e.g. writing analysis utilities which need to accept /any/ valid program and interpret it correctly. `Using' a language involves two activities: writing it, and reading it. You're only considering one of those activities, and I think it's the less important one. E.g. a reference manual would need to describe indentation, but details such as the interpretation of a mixture of tabs and spaces can be limited to don't do this, whereas a specification would need to either specify the details or at least specify that it invokes undefined behaviour. I'm confronted with some code, written by someone else, and when I run it I get an unexpected result. The language reference should be able to explain to me precisely why I get the result that I see. If it can't, it's of no value. I'm arguing that the reference manual reads too much like a specification. E.g. look at 5.2.4. List displays and tell me whether you consider that it adequately /explains/ list displays to someone wishing to use them. It doesn't adequately specify them either. That section is just poorly written. I note that the reference manual contains very few examples. For a specification, this would be quite normal, as examples can serve to undermine precision. For a reference manual, precision has to be traded for clarity, which may mean using examples where appropriate. I disagree with both claims. Examples cannot undermine precision: if the normative text is correct then an example can only demonstrate an application of the specified rules. If the normative text is wrong then the specification is broken and needs fixing. But the same applies to a reference. Either it supplies enough detail to answer every question about how programs behave or it's broken: precision is essential here, but is not -- and cannot -- be compromised by adding examples. OTOH, a tutorial often contains little more than a sequence of examples along with informal explanations as to their structure and functioning. As a result, tutorials tend to lack precision; they provide specific cases which will work and some clues as to what else is likely to work. Yes, I'm familiar with the `leave the reader to fill in the gaps in my exposition for himself' approach to documentation -- and with the unenjoyable task of fixing the reader's confused mental model afterwards. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Allowing comments after the line continuation backslash
Lawrence D'Oliveiro l...@geek-central.gen.new_zealand writes: Not surprising, since the above list has become completely divorced from its original purpose. Anybody remember what that was? It was supposed to be used in a loop, as follows: for \ Description, Attr, ColorList \ in \ ( (normal, image, MainWindow.ColorsNormalList), (highlighted, highlight, MainWindow.ColorsHighlightedList), (selected, select, MainWindow.ColorsSelectedList), ) \ : ... #end for Does this make more sense now? Ugh, no! for descr, attr, colours in [ ('normal', 'image','Normal'), ('highlighted', 'highlight','Highlighted'), ('selected','select', 'Selected')]: colourlist = getattr(MainWindow, 'Colors%sList' % colours) ## ... To be honest, there's so much regularity in that table that I'd consider generating it from a shorter list. This would obviously involve refactoring something else to eliminate the image/normal asymmetry. I'd also consider making the ColorsMumbleList attribute collection into a dictionary. Note that my columns are aligned to 8-column tab stops for easy maintenance (although my editor has used physical spaces rather than tabs). -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Compare source code
Rustom Mody rustompm...@gmail.com writes: As for tools' brokeness regarding spaces/tabs/indentation heres a thread on the emacs list wherein emacs dev Stefan Monnier admits to the fact that emacs' handling in this regard is not perfect. http://groups.google.com/group/gnu.emacs.help/browse_thread/thread/1bd0c33a3e755730/89cbd920ee651b5a?q=tabs+stefan+spaces+group:gnu.emacs.help#89cbd920ee651b5a You've misunderstood. That discussion is about configuring Emacs to not do automatic indentation when the `tab' key is pressed or when language-specific punctuation is entered. It has very little to do with tab characters in files. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: functions, list, default parameters
Steven D'Aprano st...@remove-this-cybersource.com.au writes: On Fri, 05 Nov 2010 12:17:00 +, Mark Wooding wrote: Right; so a half-decent compiler can notice this and optimize appropriately. Result: negligible difference. Perhaps the biggest cost is that now your language has inconsistent semantics: some function defaults are set on every call, and some are set once, when the function is defined, and the choice between the two happens via magic -- the compiler decides what to do, you don't. The /semantics/ are indistinguishable. The implementations are different, and I'll grant that the performance model is more complex for optimized DIC. I have mixed feelings about compiler optimizations. Things like constant folding seems to be both harmless and useful, but other optimizations not so much. It sets up a discrepancy between what the source code does and what the compiled code does, and in the case of (say) floating point code, can introduce *serious* bugs. Oooh, careful now. It's important not to muddle semantics-preserving transformations (like memoizing constant immutable objects, as I'm suggesting, or constant folding) and tolerated semantics-altering transformations such as increasing precision of intermediate floating-point values. (`Tolerated' here means that some language specifications grant specific permission for these optimizations despite the fact that they don't preserve semantics.) Semantics-altering optimizations are scary, to be approached only with great trepidation. Semantics-preserving optimizations are nearly free, except for the potentially complicated performance model. _missing = ['missing'] A curious choice for the sentinel value. We're not using Python 1.5 any longer :) Two reasons. Firstly, this comes from my Lisp background: making a list is the obvious way of producing an unforgeable object. Secondly, if you see an objects that prints as ['missing'], you have a chance of working out where it came from; for a loose object() that's kind of hard without a wabbit hunter. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: functions, list, default parameters
Dennis Lee Bieber wlfr...@ix.netcom.com writes: On Sat, 06 Nov 2010 12:37:42 +, m...@distorted.org.uk (Mark Wooding) declaimed the following in gmane.comp.python.general: Two reasons. Firstly, this comes from my Lisp background: making a list is the obvious way of producing an unforgeable object. Secondly, if you see an objects that prints as ['missing'], you have a chance of working out where it came from; for a loose object() that's kind of hard without a wabbit hunter. I think the Python form is to create a basic class instance, a la class Sentinal(object): ... pass ... _missing = Sentinal() print _missing __main__.Sentinal object at 0x011F01B0 No, that doesn't tell me where it came from at all. Given a thingy that prints like that, I still need a wabbit hunter to tell me what /this/ particular sentinel value means. Or, if one wants to get fancier (maybe stuff the class definition into some common package) class Sentinal(object): ... def __init__(self, text): ... self.text = text ... def __str__(self): ... return %s : %s % (repr(self), self.text) ... _missing = Sentinal(Missing Items) print _missing __main__.Sentinal object at 0x0120D070 : Missing Items And the advantage of all of this typing over ['missing'] is what, precisely? If I want to write Java, I know where to look; I don't. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: How to test if a module exists?
Chris Rebert c...@rebertia.com writes: if err.message != No module named extension_magic_module: Ugh! Surely this can break if you use Python with different locale settings! -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: How to test if a module exists?
Chris Rebert c...@rebertia.com writes: Since when does Python have translated error messages? It doesn't yet. How much are you willing to bet that it never will? ;-) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Silly newbie question - Carrot character (^)
Steven D'Aprano st...@remove-this-cybersource.com.au writes: If you want to argue that the Python reference manual is aimed at the wrong level of sophistication, specifically that the BNF syntax stuff should be ripped out into another document, then I might agree with you. But to argue that it's entirely the wrong kind of thing is, in my opinion, unjustified. I certainly wouldn't agree with that. The language's syntax is essential part of the language, and must be described clearly and unambiguously. Formal grammars aren't especially hard to understand, and they're pretty much everywhere, so learning how to read them is an essential skill anyway. To be honest, I reckon the Python language reference is too friendly and fluffy. The manual for F#, say, is a harder read. The Standard ML language reference is a book full of mathematical notation (inference rules for operational semantics, mainly) and little else. The Scheme language used to be described by a page or so of equations giving a translation into lambda calculus (but now that's operational semantics too) -- oh, there are prose descriptions too, but they're not easy going either in places, and the formal semantics are necessary to clear up some of the details. You Python people have it easy. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: functions, list, default parameters
Steven D'Aprano st...@remove-this-cybersource.com.au writes: defaults initialise on function definition (DID) defaults initialise on function call (DIC) I claim that when designing a general purpose language, DID (Python's existing behaviour) is better than DIC: #1 Most default values are things like True, False, None, integer or string literals. Since they're literals, they will never change, so you only need to set them once. Right; so a half-decent compiler can notice this and optimize appropriately. Result: negligible difference. #2 It's easy to get default values to initialise on function call in a language that uses initialisation on function definition semantics: just move the initialisation into the function body. Python has a particularly short and simple idiom for it: def f(x=None): if x is None: x = some_expression() That's actually rather clumsy. Also, it's using in-band signalling: you've taken None and used it as a magic marker meaning `not supplied'. Suppose you want to distinguish /any/ supplied value from a missing argument: how do you do this /correctly/? The approaches I see are (a) to invent some unforgeable token or (b) emulate the argument processing by rifling through * and ** arguments. Solution (a) looks like this: _missing = ['missing'] def foo(arg = _missing): if arg is _missing: arg = ... ... But now _missing is kicking around in the module's namespace. Fixing that is rather messy. (No, you can't just `del' it.) Maybe this can be improved: def _magic(): _missing = ['missing'] def foo(arg = _missing): if arg is _missing: arg = ... ... return foo foo = _magic() del foo Solution (b) is just too grim. But if the situations were reversed, it's hard to get the DID semantics: def f(x=None): if x is None: global _f_default_arg try: x = _f_default_arg except NameError: _f_default_arg = x = default_calculation() Ugh. This is artificially awful and doesn't correspond to existing Python DID semantics. * Python evaluates the default argument expression at function definition time. You've implemented delayed evaluation for no obvious reason. * Python evaluates the default argument expression in the enclosing environment. You've evaluated the expression in the function, again for no obvious reason. I'm interested to know why you did this. You know Python well enough that it's probably not just a misunderstanding, and you have enough integrity that it's probably not a dishonest debating tactic. A more faithful implementation of the actual semantics is considerably simpler. _default_arg = ... def func(arg = _default_arg): ... This is always correct, and actually simpler than even the standard but incorrect simulation of DIC. #3 Re-initialising default values is wasteful for many functions, perhaps the majority of them. (Of course, if you *need* DIC semantics, it isn't wasteful, but I'm talking about the situations where you don't care either way.) In current Python, nobody would write code like this: def f(x=None, y=None, z=None): if x is None: x = 1 if y is None: y = 2 if z is None: z = 3 but that's what the DIC semantics effectively does. When you need it, it's useful, but most of the time it's just a performance hit for no good reason. A smart compiler would factor out the assignment to a constant and do it once, when the function were defined -- which is just what DID semantics are. Python's compiler is already clever enough to notice a constant expression when it sees one, and memoizing the default argument values is straightforward enough. There's therefore nothing to choose between the two on constant expressions. If you're unconvinced about this being a potential performance hit, consider: No, I can see that clearly, thanks. That comes up much less frequently than the case where a default argument value should be a fresh list or dictionary, in my experience. What would you prefer, the default value to be calculated once, or every time you called f()? This situation is rare enough that I'd put up with manual memoization. #4 Just as DID leads to surprising behaviour with mutable defaults, so DIC can lead to surprising behaviour: def f(x=expression): do_something_with(x) If expression is anything except a literal, it could be changed after f is defined but before it is called. If so, then f() will change it's behaviour. Yes. Most usefully, the expression may refer to other argument values (to its left, only, presumably). This is frequently handy, not least in object constructors. This is an enormous sidetrack on what I'd hoped would be a parenthetical remark left unremarked. I'm not sure that further discussion will be especially interesting,
Re: Compare source code
Seebs usenet-nos...@seebs.net writes: Python's the only language I use where an obvious flaw, which is repeatedly observed by everyone I know who uses the language, is militantly and stridently defended by dismissing, insulting, and attacking the character and motives of anyone who suggests that it might be a bit of a nuisance. So you've not tried Lisp, then? Dissing Lisp's parentheses tends to get a pretty similar reaction. My observations on this general discussion. * Python is far from unique in its use of significant whitespace. Miranda was inferring program structure from indentation in 1985. Haskell and F# are more modern examples. * I don't have many problems with tools trashing whitespace in Python programs, though I have seen web forum software mangling indentation; since this makes nontrivial chunks of almost any programming language illegible, I'm more than willing to blame the forum software for this. I haven't personally seen indentation trashed by email software, for example (though I steer well clear of people who try to send me HTML mail). * I /do/ have a significant problem with cutting and pasting code in Python. In most languages, I can haul a chunk of code about, hit C-M-q, and Emacs magically indents the result properly. This is, unfortunately, impossible with Python. It has caused me real bugs, and I have to be extra careful to fix the indentation up. * I've just noticed that Emacs's Python mode has a magic keystroke which appears to do the right thing for cut-and-pasted code. This is symptomatic of a bigger problem: simply by being different from the mainstream, Python requires that one work with it differently. It requires different tools, and different techniques. Many languages use some kind of brackets to mark substructure, so tools have become good at handling bracketed substructure, whether for automatic indentation or navigation. Python marks (some) substructure differently, so users need to learn new techniques or tools for working with it. I /like/ Python. I use it frequently. I /don't/ want to change its structure marked by indentation. I'm /willing/ to put up with some inconvenience because Python makes up for it in other ways. But there /is/ inconvenience, and it does need putting up with. I think the benefits are worth the costs; others may disagree. -- [mdw], a smug Lisp weenie at heart. -- http://mail.python.org/mailman/listinfo/python-list
Re: Compare source code
Tim Harig user...@ilthio.net writes: Python is the only language that I know that *needs* to specify tabs versus spaces since it is the only language I know of which uses whitespace formating as part of its syntax and structure. You need to get out more. Miranda, Gofer, Haskell, F#, make(1), and many others, all use indentation to indicate structure; YAML isn't a programming language, but it also uses indentation to indicate structure, as do a number of wiki markup languages; there are also representations of Lisp S-expressions which use indentation instead of parentheses. Mixed usage may be annoying in other languages; but, it breaks Python. I disagree. The Haskell '98 report specifies (correctly) that tabs are every eight columns, and a tab moves to the next tab stop. Python makes the same specification; it's just the users who actually want to stamp out tabs. Flamebait: it's not the tabs that cause the problem: it's that some people are under the mistaken impression that the position of tab stops in text files is a matter for local preference. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Allow multiline conditions and the like
Chris Rebert c...@rebertia.com writes: Or, if possible, refactor the conditional into a function (call) so it's no longer multiline in the first place. No! This /increases/ cognitive load for readers, because they have to deal with the indirection through the name. If you actually use the function multiple times, the mental overhead of forming the abstraction and associating it with the function name is shared across the various call sites and it's probably worth it. If it's only called once, leave it inline. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Compare source code
Tim Harig user...@ilthio.net writes: So, your telling me that mixing tabs and spaces is considered a good practice in Haskell? It doesn't seem to be a matter which is discussed much. I think Haskell programmers are used to worrying their brains with far more complicated things like wobbly[1] types. I would argue that text files do not have tab stops -- text editors do. So long as you use tabs for all of your indenting, it is quite safe to set the editors tab stops however one likes since the editor's tab stop doesn't effect the output of the file. This is wishful thinking. Firstly, code written with a narrow indentation offset (e.g., two spaces) can take up an uncomfortable width when viewed with a wider offset. Secondly, if you want other parts (e.g., per-line comments) of lines with different indentations to align, then you'll have to take into account the tab width. Technically, you could arrange that between any pair of alignment points of any pair of lines there are the same number of tab characters; but this is also doomed to uncomfortably wide lines; it also suffers because it imposes an /a priori/ upper bound on the indentation level. [1] Proper technical term. I kid you not. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Man pages and info pages
Tim Harig user...@ilthio.net writes: When the GNU folk decided to clone *nix they decided that they knew better and simply decided to create their own interfaces. This isn't the case. Actually Info has a long history prior to GNU: it was the way that the documentation was presented at the MIT AI lab. In fact, Info was used rather like a modern wiki. The operating system they used, called ITS, didn't have a concept of file permissions, and users were encouraged to improve documentation (and programs). The original Info viewer was implemented in Emacs (which also originated in ITS, years before GNU). Texinfo was a GNU innovation: the idea that you could build both the Info document and a nice printable manual from a single source was novel, as was the application to Unix. But, since Stallman was documenting large software systems like Emacs and GCC, it doesn't seem unreasonable to provide manuals which are somewhat more discursive and leisurely than traditional Unix manpages. I have a printed copy of the GNU Emacs 18 manual (from 1987): it's almost 300 pages long. The modern manual for Emacs 23 is several /times/ larger than this. Man pages don't scale that well. I do agree it's annoying that the official coreutils documentation is in Texinfo. Actually, the left arrow key does not work at all intuitively. One would expect that it should go back to the previous page as it would in lynx, etc. It does not. It moves the cursor so you can hit links. The l key takes you back through your recent viewing history -- and has done for thirty years. By tradition 'n' and 'p' are broken for scrolling in a page. 'b' is often used in place of p but that seems to take one back to the top of the page. Space and backspace are an older tradition. The s key for a search is another example that has already been discussed. I find C-s more useful in Info, because it searches interactively. I frequently get muddled when I try to search in `modern' programs like web browsers, because they've gratuitously made C-s try to save the page (something one hardly ever wants to do) rather than search. (Finding is different: finding is what happens at the end of a /successful/ search. So C-f is poorly chosen.) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Ways of accessing this mailing list?
John Bond li...@asd-group.com writes: Hope this isn't too O/T - I was just wondering how people read/send to this mailing list, eg. normal email client, gmane, some other software or online service? My normal inbox is getting unmanageable, and I think I need to find a new way of following this and other lists. I read and post to it as comp.lang.python. I maintain a local NNTP server, which interacts with my ISP's news server. I read and post news (and mail) using GNU Emacs and Gnus. (Interestingly, if enormous folders are your problem, Gnus can apply news-like expiry rules to email folders.) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Compare source code
Tim Harig user...@ilthio.net writes: I use simple comments that are not effected by white space. I don't waste my time trying to make comments look artistic. They are there to convey information; not to look pretty. I really detest having to edit other peoples comment formatting where you have to re-align everything if the length of any of comment lines change. I view source code as primarily a means of communication with human readers, and only secondarily as being machine readable. I therefore think it's worth the effort to make source code readily legible, for example by making effective use of horizontal and vertical whitespace. A long time ago, I spent a little while studying graphic design, so I try to keep an eye on this sort of thing. I'm interested in line length for two reasons: firstly, because I believe that there's an optimum line length for easy and rapid reading, which is probably a bit less than 80 columns; and secondly because I find that I make more effective use of the available space on my screen if I have several narrow columns rather than a few wide ones -- since most lines in source files are short, a wide column ends up being mostly empty on the right hand side, which is wasteful. It's true that a source file is not the same as a typeset document: the most obvious difference is that source files are modified over time, sometimes by many hands, and that therefore some of the tradeoffs are different. I dislike `pretty' boxes around large comments, for example, because maintaining the right hand edge is unnecessarily tedious. But sometimes careful alignment can help a reader spot a symmetry or find his way through a repetitive section such a table more easily. (Unfortunately, I appear to have strange ideas about what `legible' means...) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: functions, list, default parameters
Lawrence D'Oliveiro l...@geek-central.gen.new_zealand writes: In message 20101021235138.609fe...@geekmail.invalid, Andreas Waldenburger wrote: While not very commonly needed, why should a shared default argument be forbidden? Because it’s safer to disallow it than to allow it. Scissors with rounded ends are safer than scissors without. Chopsticks and plastic sporks are safer than metal cutlery. We have sharp things because they're /useful/. Similarly, having mutable objects as argument defaults can be useful. (Based on experience with other languages, I suspect that evaluating the default expression afresh for each call where it's needed would be more useful; but it's way too late to change that now.) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: functions, list, default parameters
Lawrence D'Oliveiro l...@geek-central.gen.new_zealand writes: Mediocre programmers with a hankering towards cleverness latch onto it as an ingenious way of maintaing persistent context in-between calls to a function, completely overlooking the fact that Python offers much more straightforward, comprehensible, flexible, and above all maintainable ways of doing that sort of thing. It does nowadays. Once upon a time, Python didn't have proper closures, and argument defaults, evaluated at function-definition time, were the only way of capturing data from the surrounding environment. You may be confusing `mediocre' with `old-fashioned', and `a hankering towards cleverness' with `wanting to run code on old Python interpreters'. This last may be because the relevant code was written back when those `old' interpreters were shiny and new. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Man pages and info pages
Tim Harig user...@ilthio.net writes: Right, and in info with the default key bindings, backspace takes me to the command help. I would have expected it to either scroll up the page or take me to the previously visited node. Sounds like your terminal is misconfigured. Backspace should produce ^?, not ^H. (Delete should produce some awful escape sequence.) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: [OFF] sed equivalent of something easy in python
Jussi Piitulainen jpiit...@ling.helsinki.fi writes: Daniel Fetchinson writes: The pattern is that the first line is deleted, then 2 lines are kept, 3 lines are deleted, 2 lines are kept, 3 lines are deleted, etc, etc. So, is there some simple expression in Python for this? (item for i, item in enumerate(input) if (i + 4)%5 2) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Strong typing vs. strong testing [OT]
Steven D'Aprano steve-remove-t...@cybersource.com.au writes: Well, what is the definition of pi? Is it: the ratio of the circumference of a circle to twice its radius; the ratio of the area of a circle to the square of its radius; 4*arctan(1); the complex logarithm of -1 divided by the negative of the complex square root of -1; any one of many, many other formulae. None of these formulae are intuitively correct; the formula C = 2πr isn't a definition in the same sense that 1+1=2 defines 2. The point that I was trying to get across is that, until somebody proved the formula, it wasn't clear that the ratio was constant. There are several possible definitions of `2'. You've given a common one (presumably in terms of a purely algebraic definition of the integers as being the smallest nontrivial ring with characteristic 0). Another can be given in terms of Peano arithmetic, possibly using an encoding of Peano arithmetic using only the Zermelo-- Fraenkel axioms of set theory: at this point one has only a `successor' operation and must define addition; the obvious definition of 1 and 2 are s(0) and s(s(0)) respectively, and one then has an obligation to prove that s(0) + s(0) = s(s(0)), though this isn't very hard. I think my preferred definition of `pi' goes like this (following Lang's /Analysis I/). Suppose that there exist real functions s and c, such that s' = c and c' = -s, with s(0) = 0 and c(0) = 1. One can prove that a pair of such functions is unique, and periodic. Define pi to be half the (common) period of these functions. (Now we notice that they factor through the quotient ring R/(2 pi) and define `sin' and `cos' to be the induced functions on the quotient ring.) Would the world be a better place if we had a name for 2 pi rather than pi itself? -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Lisp mentality vs. Python mentality
Carl Banks pavlovevide...@gmail.com writes: Graham, for his part, doesn't seem to appreciate that what he does is beyond hope for average people, and that sometimes reality requires average people to write programs. I think he understands that perfectly well. But I think he believes that the sorts of tools which help average people write programs get in the way of true wizards. I think I agree. On the other hand, I don't think Python actually does get in the way very much. -- [mdw], Lisp hacker. -- http://mail.python.org/mailman/listinfo/python-list
Re: python list handling and Lisp list handling
Mark Tarver dr.mtar...@ukonline.co.uk writes: But are Python lists also indistinguishable from conventional Lisplists for list processing. For example, can I modify a Python list non-destructively? No. Are they equivalent to Lisp lists. Can CAR and CDR in Lisp be thought of as def car (x): return x[0] def cdr (x): return x[1:] Not in the presence of side-effects, no. The slice-extration operation on lists constructs a copy of the original, and mutating the original doesn't affect the copy. Here's a simple example. [Load your definitions...] In [1]: def car (x): return x[0] ...: In [2]: def cdr (x): return x[1:] ...: [Python] [Common Lisp] In [3]: a = [1, 2, 3, 4] CL-USER (setf a (list 1 2 3 4)) (1 2 3 4) In [4]: b = cdr(a) CL-USER (setf b (cdr a)) (2 3 4) In [5]: a[2] = 'banana'CL-USER (setf (third a) banana) banana In [6]: a CL-USER a Out[6]: [1, 2, 'banana', 4](1 2 banana 4) In [7]: b CL-USER b Out[7]: [2, 3, 4]! (2 banana 4) Also, note: In [8]: b is cdr(a)CL-USER (eq b (cdr a)) Out[8]: False! T Your Python `cdr' operation conses. Until you create it explicitly, there is no Python value corresponding to `all but the first element of this list'. But, apart from the performance and sharing characteristics, they're the same. I think those are pretty big differences, though. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Definition of Pythonic?
John Yeung gallium.arsen...@gmail.com writes: A couple of others have already mentioned the Zen of Python, available at the Python command prompt. I would agree with that, but also add the caveat that none of the principles expressed there are hard-and- fast rules. Indeed, I'd suggest that the very lack of hard-and-fast rules is typical of the Python approach. The fact is, it's impossible to satisfy every principle in every situation. To me, Python distinguishes itself for how well it balances all of them. Compromise is a word that comes up a lot when talking about the design of Python. To some, that has a negative connotation; to me, it's an inevitable consequence of being practical. Agreed. Then again, all language design is a compromise, between factors like runtime efficiency, simplicity of implementation, tractability of semantics (for various classes of users), supportability by tools, and expressive power. Python inhabits what seems to me to be a particularly sweet spot on this rather complex landscape. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: siple for in expression
Matko ivastipan...@inet.hr writes: Can someone help me to understand the following code: uv_face_mapping = [[0,0,0,0] for f in faces] It constructs a fresh list, with the same number of elements as are in the iterable object referred to by `faces', and where each element is a distinct list of four zero-valued integer objects; it then makes uv_face_mapping be a name for this list. (This is therefore not the same as uv_face_mapping = [[0, 0, 0, 0]] * len(faces) which constructs a list, each of whose elements is (well, refers to) the /same/ list of four zero-valued integers.) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: why cannot assign to function call
Ethan Furman et...@stoneleaf.us writes: Mark Wooding wrote: Here's what I think is the defining property of pass-by-value [...]: The callee's parameters are /new variables/, initialized /as if by assignment/ from the values of caller's argument expressions. My soundbite definition for pass-by-reference is this: The callee's parameters are merely /new names/ for the caller's argument variables -- as far as that makes sense. Greetings, Mark! You posted to the whole group -- probably using a wide-reply option while reading the mailing list. Still, I'll give an answer here in order to help any other readers of the list or newsgroup. However, as far as I'm concerned, this discussion is basically at an end and I'm not really interested in starting it up all over again. To that end, I've set followups to `poster'. I shall continue reply to private email which seems interested in a sensible discussion. I was hoping you might be able to clarify those last two sound bites for me -- I think I understand what you are saying, but I'm confused about how they relate to Python... Specifically, how is a new name (pbr) different, in Python, from a new name initialized as if by assignment (pbv)? It seems to me than you end up with the same thing in either case (in Python, at least), making the distinction non-existent. You've missed a level of indirection. In particular, `names' aren't things that you initialize. They're things that you /bind/ to variables. The crucial difference is that, in pass-by-value, new variables are created as an intrinsic part of the process, whereas in pass-by-reference, new variables are not (usually) created, and instead the formal parameter names are bound to the caller's pre-existing argument variables. It's worth noting that I use the terms `name' and `binding' in different ways from most of the Python community. This is unfortunate. The discrepancy is actually because the Python meanings of these words are not the same as the meanings in the wider computer science and mathematical communities. For example, many Python users seem to use `binding' to mean `assignment', which is a shame because it leaves the concept that is usually called `binding' without a name. So I'll stick with the wider meanings. A while ago, I posted an essay -- to this group -- which may help explain the concepts: Message-ID: 8763k14nc6.fsf@metalzone.distorted.org.uk http://groups.google.com/group/comp.lang.python/msg/f6f1a321f819d02b On with the question. def func(bar): bar.pop() Pass-by-reference: foo = ['Ethan','Furman'] func(foo) # bar = foo Pass-by-value: foo = ['Python','Rocks!'] func(foo) # bar is new name for foo # is this any different from above? If I have this right, in both cases foo will be reduced to a single-item list after func. You're correct. So: we can conclude that the above test is not sufficient to distinguish the two cases. Any further explanation you care to provide will be greatly appreciated! This test is sufficient to distinguish: def test(x): x = 'clobbered' y = 'virgin' test(y) print y If it prints `virgin' then you have call-by-value. If it prints `clobbered' then you have call-by-reference. Let's examine the two cases, as I did in the essay I cited above. I'll do call-by-value first. First, we define a function `test'. Then, we initialize `y'. It's worth examining this process in detail. The name `y' is initially unbound. so it is implicitly bound to a fresh variable. Then, (a reference to) the string object 'virgin' is stored in this variable. We can show this diagrammatically as follows. y (in global env.) [VAR] --- 'virgin' (In the diagrams, === denotes a binding relationship, between names and variables; and --- denotes a reference relationship, between variables and values.) Next, we call the `test' function. Call-by-value says that we must evaluate the argument expressions. There's only one: `x'. The value of a name is obtained by (a) finding which variable is bound to the name, and (b) extracting the value from this variable. Well, the variable is the one we just bound, and the value stored is (the reference to) the string 'virgin'. So the result of evaluating the argument expressions is simply (the reference to) that string. The function has one parameter, `y'. A new environment is constructed by extending the global environment. In this new environment, the name `y' is bound to a fresh variable -- distinct from all others, and especially from the variable bound to `x' -- and in that variable we store the value of the corresponding argument expression. Result: the function body is executed in an environment which is like the global environment except that `y' is bound to a fresh variable containing 'virgin'. y (in global env
Re: Using while loop and if statement to tell if a binary has an odd or even number of 1's.
Duncan Booth duncan.bo...@invalid.invalid writes: Mark Dickinson dicki...@gmail.com wrote: [snip] while n: count += 1 n = n-1 return count is_even = count_set_bits(the_int) % 2 == 0 ...but anyone submitting this as a homework solution had better be prepared to explain why it works. I remember a programming exercise when I was an undergraduate and anyone who *didn't* use that trick got marked down for writing inefficient code. Curious. I don't see why def parity(x): b = 2 l = 1 while True: b = l if x b: break l = 1 while l: b = l x ^= x l x = b - 1 l = 1 return x 1 is any less efficient. Indeed, it seems more so to me. The number of top-level loop iterations is bounded by the logarithm of the total number of bits in the input rather than the Hamming weight. In terms of single-precision operations (if we're dealing with bignums) the analysis is more complicated; but the number of single-precision operations in one of my loops is a linear function of l (assuming that the comparison is done sensibly), and l increases and decreases geometrically, so I have performance which is O(log x). Assuming no special Hamming-weight distribution on the input, the `efficient' version takes O(log^2 x) single-precision operations. Given an /a-priori/ upper bound on the length of the input, e.g., it fits in a machine word, the above technique is still probably faster. That is, assuming arithmetic and bitwise operations on integers take constant time, my version runs in O(log log x) time whereas the `efficient' version takes O(log x) time. (My function returns the complement of the value requested. Fixing it is obviously trivial.) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: is python Object oriented??
Russ P. russ.paie...@gmail.com writes: Imagine you own a company, and you decide to lease an office building. Would you expect the office doors to have locks on them? Oh, you would? Why? You mean you don't trust your co-workers? What are locks but enforced access restriction? Huh? The lock on the door isn't to keep the coworkers out. It's to let them /in/ while keeping everyone else out. So I don't really see the analogy. Or are you talking about the individual offices? If so, then I'd expect the locks to be /used/ only under rather unusual circumstances. If someone in the office has something to hide, I think that's rather suspicious, actually... -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: is python Object oriented??
Steven D'Aprano ste...@remove.this.cybersource.com.au writes: Now, that's a toy example. Languages like Ada make correctness proofs, well, perhaps not easy, but merely difficult compared to impossible for languages like Python. Say `generally impractical' rather than `impossible' and I'll agree with you. But I'm not actually sure that the situation for Python with respect to correctness proofs is significantly harder than it is for C. Certainly Ada (or at least dialects of Ada) have features which make proof-supporting tools easier; I'm not aware of such proof support for other languages. Actually, if you're starting from a formal specification in Z, say, and implementing in Python, well, the Z checker will already have ensured that your specification is well typed; your proof that the implementation follows the specification will automatically contain a well-typed-ness proof of your implementation regardless of whether the compiler provides static verification. To bring it back to private/public attributes, side-effects make correctness proofs difficult. Modifications of attributes are side- effects. When attributes are subject to being modified by arbitrary code, it is harder to reason about the correctness of the code: class Inverter(object): def __init__(self, x): # Pre-condition: x is always a float if x: self.x = x else: raise ValueError(x must not be zero) # Post-condition: if self.x exists, it is a non-zero float def invert(self): return 1.0/self.x Is method invert correct? I'd argue that it isn't, and in fact that the specification is wrong. In particular, it ought to be a precondition that x is nonzero. At this point you can dump the explicit check at the cost of imposing a proof obligation on the caller. No, it is not, because the invariant that self.x is non-zero may have been broken by some arbitrary piece of code elsewhere. It's not stated as an invariant. It's stated as a post-condition, which is indeed true (almost[1]) regardless of the behaviour of other parts of the program. [1] A subclass may have already set self.x before invoking Inverter.__init__. If you explicitly `del self.x' before raising the exception, the subclass can still defeat you by passing the reference to the half-constructed object to another thread which mutates the object at an inconvenient time. I mention all of this merely to avoid pedantry in follow-ups. I'd also argue that maintaining the invariant about self.x is the responsibility of code that messes with self.x, and therefore it is /legitimate/ to modify self.x from external code which maintains the invariant. Our ability to reason about the correctness of the code is weakened significantly. Sticking an underscore in front of x does not help: there's nothing to stop some arbitrary function elsewhere changing _x to zero. Dichotomy for you. * EITHER the other code is written to the same high standards, in which case it will come with appropriate specifications, preconditions, postconditions, invariants and proofs for whatever it does, even -- especially -- if it involves grubbily messing about with your module's innards (so everything is fine); * OR the other code doesn't meet your high standards, in which case all bets are off anyway, from the point of view of formal-methods types at any rate (so you can wash your hands of the whole affair). (1) Paranoia. Make the developer responsible for checking everything all the time: [...] (2) Hope the error never occurs, and if it does, let the caller deal with it. [...] There is a third strategy, sadly not available to Python programmers: prevention by catching potential errors at compile-time. Four: Describe your interface clearly, specify the behaviour of functions and so on; and leave whoever messes with your module with the task of proving -- to whatever level of formality is required by their project -- that what they've done is sane and reasonable. In fact, since whatever one does in a project should be held to this standard, whether it involves grubbing about inside undocumented internals or not, there's nothing particularly special about this case. Good job, really, since Python doesn't distinguish either. ;-) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Where how to deallocate resources in Python C extension
fredbasset1...@gmail.com writes: I've written a C extension, see code below, to provide a Python interface to a hardware watchdog timer. As part of the initialization it makes some calls to mmap, I am wondering should I be making balanced calls to munmap in some kind of de-init function? The kernel should remove the mapping when your process exits anyway -- otherwise the world would be left in an inconsistent state if your process got killed by SIGKILL for example. Do Python extensions have d'tors? No. But you can cheat: stash some object whose tp_del slot does your cleanup in your extension's module under some funny name. (And woe betide anyone who dels the funny name prematurely!) I'm not sure I'd bother. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: structs
Keith Thompson ks...@mib.org writes: Gary Herron gher...@islandtraining.com writes: Python *is* object-oriented I disagree. Care to provide proof of that statement? AWOOGA! The article I'm following up to (together with at least one other) is a forgery, and the Followup-To header is set to comp.lang.c as part of an effort to (a) disrupt that newsgroup, and (b) discredit Keith Thompson, who is a respected and capable contributor to that group. This is a request to other readers to take special care over responding to controversial articles, and particularly to watch for strange Followup-To headers. Thanks for listening. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Date Comparison
mohana2...@gmail.com writes: I need to compare two dates and find the number of days between those two dates.This can be done with datetime module in python as below, but this is not supported in Jython. example from datetime import date a=datetime.date(2009,2,1) b=datetime.date(2008,10,10) c= a-b c.days 114 I don't understand your problem. Jython 2.2.1 on java1.6.0_0 Type copyright, credits or license for more information. from datetime import date a=datetime.date(2009,2,1) b=datetime.date(2008,10,10) c = a - b c.days 114 -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Number of bits/sizeof int
Jon Clements jon...@googlemail.com writes: The int() type gained a bit_length method that returns the number of bits necessary to represent its argument in binary: Any tips on how to get this in 2.5.2 as that's the production version I'm stuck with. def nbits(x): ## Special cases. if x == 0: return 0 elif x 0: x = -x ## Find upper bound of the form 2^(2^n) = x. n = 1 while True: y = x n if y == 0: break x = y n = 1 ## Now binary search until we're done. a = n while n 0: n = 1 y = x n if y 0: x = y a += n return a -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Number of bits/sizeof int
John Machin sjmac...@lexicon.net writes: 3 can be represented in 2 bits and at the same time -3 can be represented in 2 bits?? But 2 bits can support only 2 ** 2 == 4 different possibilities, and -3 .. 3 is 7 different integers. Yeah, I made some arbitrary choices about what to do with non-positive inputs. If you prefer other answers, use 'em. My ones work well with signed-magnitude representations where the sign is stored separately. ## Find upper bound of the form 2^(2^n) = x. Possibly you mean 2 ** ( 2 ** n) = x I write maths in comments, not Python. Feel lucky I didn't write it in LaTeX. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: is python Object oriented??
Russ P. russ.paie...@gmail.com writes: I am not sure why people keep mentioning that Python is not Java. As a slogan, it is rather misleading. Python is not C++, Ada, or Scala either. All of those languages have enforced access restriction. Why only mention Java? Because Java is a well-known member of a family of object-oriented languages (or at least languages supporting object-oriented programming). `Python is not Java' is somewhat of a slogan, intended to convey the message that Python, quite intentionally, does not behave in the same way as other languages you may be familiar with. Smalltalk's visibility features are very different from C++ and Java: a method can mess with its own object's (i.e., the recipient of the message which caused the method to be invoked) instance variables but no others -- a restriction enforced syntactically, since there is simply no way of referring to a different instance's variables. There is no restriction whatever on sending messages to other objects. Self abandons the concept of instance variable (and of class, for that matter), and access controls with it. The Common Lisp Object System provides no access control features (though one could probably implement some using the MOP, were one sufficiently motivated); however, CL's package system is better placed for this job anyway. Other object systems for Lisp-family languages tend to be similar. The Lisp Machine's Flavors -- the first object system with multiple inheritance -- relied on the package system for access control; CLOS-like systems for Scheme, which lacks packages, tend not to bother at all. (The package system controls the mapping from tokens read from, say, files to symbols; packages can export some of their symbols, so you can refer to, say, MDW:FOO if package MDW exports symbol FOO, or you can `use' package MDW in your own package to make FOO refer to MDW:FOO. The package system tries to keep you honest rather than acting as an enforcement mechanism: even if MDW doesn't export BAR, you can still talk about MDW::BAR -- note the double-colon -- as much as you like. Working at the name-to-symbol level allows the package system to operate uniformly on all the various namespaces in Lisp.) Perl's object system provides no access controls. Ruby does, following Simula, though it uses C++-ish `private' for Simula's `hidden'. If that's the case, you have my sympathies, but let's not pretend that Java is the only popular OO language with enforced access restrictions. No, but let's not pretend either that such features are essential to object orientation, or that they are even typical of object systems outside of a particular (admittedly popular) subfamily. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: How to get atexit hooks to run in the presence of execv?
ro...@panix.com (R. Bernstein) writes: Recently, I added remote debugging via TCP sockets. (Well, also FIFO's as well but closing sockets before restarting is what's of concern.) I noticed that execv in Python 2.5.2 doesn't arrange exit hooks to get called. Should it? I'd consider that to be highly unusual. Certainly, the C atexit(3) function is called only in response to a call to exit(3) (possibly implicitly by returning from main), and not by execve(2) or any of its little friends. Your specific problem is to do with file descriptors, so it's probably best dealt with using the close-on-exec flag: from fcntl import fcntl, F_GETFD, F_SETFD, F_CLOEXEC sk = socket(...) ## ... fcntl(sk.fileno(), F_SETFD, fcntl(sk.fileno(), F_GETFD) | FD_CLOEXEC) Now the socket will be magically closed when you exec.. another program. Finally, can I urge against TCP sockets in an application like this? Certainly without adequate authentication, it will simply be insecure even within a single multiuser host (e.g., using localhost only) -- and assuming that even a home machine has only a single user is becoming less realistic. Unix-domain sockets live in the filesystem, and access to them is limited using the standard filesystem mechanisms. If you're expecting inter-host communications (e.g., remote debugging), it's a good idea to protect the session using TLS or something (much as I dislike the TLS certification/public-key- distribution model it's way better than nothing at all). -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Doc for extended call syntax; was: Re: unzip array of arrays?
Bryan Olson fakeaddr...@nowhere.org writes: Mark Wooding wrote: There's a full description of it in 5.4.3 in the Language Reference, but apparently not indexed. So I guess this means I can duck out of writing up a lecture on my own understanding of Python's extended call syntax. Great. I think I grock the extended call syntax, and when the question came up I was surprised not to be able to find where I learned it. Mark, where exactly does one look to see this full description? I typoed, sorry! I should have written 5.3.4: http://www.python.org/doc/2.5/ref/calls.html The description of the fancy * and ** syntax starts with `If the syntax ``*expression'' appears in the function call...'. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list