Prev: Solaris 2.6 boot errors
Next: Programming intro book ch1 and ch2 (Windows/Python 3) - Request For Comments
From: Mensanator on 18 Dec 2009 18:26 > The second deviation is that since most names are constants, Really? Does that mean you don't use literals, to save the time required to convert them to integers? Isn't that done at compile time? So, instead of doing the Collatz Conjecture as while a>1: f = gmpy.scan1(a,0) if f>0: a = a >> f else: a = a*3 + 1 You would do this? zed = 0 one = 1 two = 2 twe = 3 while a>one: f = gmpy.scan1(a,zed) if f>zed: a = a >> f else: a = a*twe + one Does this really save any time? Now, it's a different story if you're using the gmpy module. You DON'T want to use literals in loops involving gmpy, because they would have to be coerced to .mpz's on every pass through the loop. In that case, you DO want to use constants as opposed to literals: ZED = gmpy.mpz(0) ONE = gmpy.mpz(1) TWO = gmpy.mpz(2) TWE = gmpy.mpz(3) while a>ONE: f = gmpy.scan1(a,0) # int used here, so it can be a literal if f>ZED: a = a >> f else: a = a*TWE + ONE And yes, the time savings can be tremendous, especially when 'a' has over 50,000 decimal digits. .. I do not follow PEP > 8's recommendation to use uppercase names of constants. In fact almost no Python > code does, Mine does when I use gmpy. Otherwise, the notion that "most names are constants" is generally false.
From: Alf P. Steinbach on 18 Dec 2009 19:25 * Mensanator: >> The second deviation is that since most names are constants, > > Really? Does that mean you don't use literals, to save the time > required to convert them to integers? Isn't that done at compile > time? > > So, instead of doing the Collatz Conjecture as > > while a>1: > f = gmpy.scan1(a,0) > if f>0: > a = a >> f > else: > a = a*3 + 1 > > You would do this? > > zed = 0 > one = 1 > two = 2 > twe = 3 > while a>one: > f = gmpy.scan1(a,zed) > if f>zed: > a = a >> f > else: > a = a*twe + one That seems to have no relation to what you quoted / responded to. On the other hand, if there is some specific r�le played by the 3 above, where some other value (like e.g. 5) might be used instead, then a self descriptive name for that r�le might be good. Such reasonable naming (not what you did above) then allows easier modification of and makes it easier to understand the code. That said, and a bit off-tangent to your comment's main thrust, the time spent on coding that repeated-division-by-2 optimization would, I think, be better spent googling "Collatz Conjecture" -- avoiding writing /any/ code. ;-) > Does this really save any time? If by "it" you mean the silly naming, no it doesn't. On the contrary, it wastes time, both for writing the code and reading it. Generally, IMO, think about the clarity of your code. If naming something increases clarity, then name the thing. If it doesn't increase clarity, don't. > Now, it's a different story if you're using the gmpy module. > You DON'T want to use literals in loops involving gmpy, because > they would have to be coerced to .mpz's on every pass through the > loop. > > In that case, you DO want to use constants as opposed to literals: > > ZED = gmpy.mpz(0) > ONE = gmpy.mpz(1) > TWO = gmpy.mpz(2) > TWE = gmpy.mpz(3) > while a>ONE: > f = gmpy.scan1(a,0) # int used here, so it can be a literal > if f>ZED: > a = a >> f > else: > a = a*TWE + ONE > > And yes, the time savings can be tremendous, especially when 'a' > has over 50,000 decimal digits. Yeah, good point. Few languages have compile time evaluation of logically constant expressions. C++0x will have that feature (called 'constexpr' IIRC) but in Python, current C++ etc. it's just a good idea to precompute values, and name them, rather than computing them again and again where they're needed. > . I do not follow PEP >> 8's recommendation to use uppercase names of constants. In fact almost no Python >> code does, > > Mine does when I use gmpy. Otherwise, the notion that "most names > are constants" is generally false. No, it depends on what you mean by "constant". The problem with Python, as Google noted, is that the language is so excessively dynamic: even names of routines are variables, and there /are/ no named user defined constants except logically, in the programmer's mind. And logically (that is, at the "in the programmer's mind" level), if you define "constant" as a name whose value will not change after initialization, then routine names are constants. However, if you define "constant" as only a global scope (that is, module scope) name that denotes a boolean, numerical or string or Null value and that doesn't change after initialization, then your statement about the scarcity of constants appears to be true, but using a practically useless definition. I think for such constants exported by modules it's a good idea to at least provide uppercase names so as conform to very firmly established convention. There might even be tools that rely on that convention. But for application code the uppercase names are just distracting, and they don't help you... Cheers & hth., - Alf
From: Steven D'Aprano on 18 Dec 2009 22:03 On Sat, 19 Dec 2009 01:25:48 +0100, Alf P. Steinbach wrote: > That said, and a bit off-tangent to your comment's main thrust, the time > spent on coding that repeated-division-by-2 optimization would, I think, > be better spent googling "Collatz Conjecture" -- avoiding writing > /any/ code. ;-) That's a strange thing to say. >> Now, it's a different story if you're using the gmpy module. You DON'T >> want to use literals in loops involving gmpy, because they would have >> to be coerced to .mpz's on every pass through the loop. [...] > Yeah, good point. Few languages have compile time evaluation of > logically constant expressions. Surely that's an implementation issue rather than a language issue. > C++0x will have that feature (called > 'constexpr' IIRC) but in Python, current C++ etc. it's just a good idea > to precompute values, and name them, rather than computing them again > and again where they're needed. CPython 2.5 and on has a keyhole optimizer that replaces many constant expressions with pre-computed values. # Python 2.4 >>> dis.dis(compile('1+1', '', 'eval')) 0 0 LOAD_CONST 0 (1) 3 LOAD_CONST 0 (1) 6 BINARY_ADD 7 RETURN_VALUE # Python 2.5 >>> dis.dis(compile('1+1', '', 'eval')) 1 0 LOAD_CONST 1 (2) 3 RETURN_VALUE Unfortunately it doesn't help Mensanator's case, because there's no way to tell the compiler to generate mpz objects instead of int objects, and expressions such as gmpy.mpz(0) are not recognised as compile-time constants. >> Mine does when I use gmpy. Otherwise, the notion that "most names are >> constants" is generally false. > > No, it depends on what you mean by "constant". All names are constant. Always. The Python language does not support renaming names -- as far as I know, no language does. > The problem with Python, > as Google noted, is that the language is so excessively dynamic: even > names of routines are variables, Don't say that, that is confusing the name with the value. The terms "constant" and "variable" refer to the values bound to a name, not the name itself: what you mean is that even routines are variables. Consider the following Pascal declaration: const a = 1; var b: integer; Neither name 'a' nor 'b' ever change; a is always a and b is always b. You wouldn't describe b as a constant because the name never changes, would you? What matters is that the value assigned to the name can, or can't, be changed by the caller. Like any other language, Python *names* are always constant: you can create them at will (without needing a declaration); you can delete them (with the del statement, something Pascal doesn't allow you to do); but there's no way to change a name once it exists. Obviously it would be misleading to claim that Python name/object bindings ("variables") are therefore constant because of this. So how would I say what you are trying to say, but in a less-misleading fashion? Names can always (well, almost -- there are a few exceptions) be rebound, regardless of whether they are currently bound to a data object (string, int, float...) or a routine (function, method...). Since the name by which we refer to a function can be rebound, we refer to the name/object binding as variable rather than constant -- exactly the same as any other name/object binding. Or the shorter way: Since all names can be rebound, regardless of what value they have (int, string, function, whatever) all names are variables and Python has no constants other than special pre-defined names like None. > and there /are/ no named user defined > constants except logically, in the programmer's mind. Yes, that is correct, although there are tricks you can do to make slightly-more-constant-like constants, such as Alex Martelli's "constant module" recipe in the Cookbook, but there are no true constants in Python. > And logically > (that is, at the "in the programmer's mind" level), if you define > "constant" as a name whose value will not change after initialization, > then routine names are constants. Some languages enforce that, and in those languages, it makes sense to describe functions as constants. Python is not one of those languages. > However, if you define "constant" as only a global scope (that is, > module scope) name that denotes a boolean, numerical or string or Null > value and that doesn't change after initialization, then your statement > about the scarcity of constants appears to be true, but using a > practically useless definition. I won't speak for Mensanator, but I wouldn't be so restrictive about the *types* of data that constants can hold. Not in Python, at least, other languages can and do limit the types of constants to a handful of predefined types known to the compiler. Nor would I say that "constants" (note the scare-quotes) can only occur in module scope. There's nothing wrong with naming "constants" in other scopes, although I must admit I'm a tad less consistent about doing so than I should. -- Steven
From: Alf P. Steinbach on 18 Dec 2009 22:29 * Steven D'Aprano: > On Sat, 19 Dec 2009 01:25:48 +0100, Alf P. Steinbach wrote: > >> That said, and a bit off-tangent to your comment's main thrust, the time >> spent on coding that repeated-division-by-2 optimization would, I think, >> be better spent googling "Collatz Conjecture" -- avoiding writing >> /any/ code. ;-) > > That's a strange thing to say. No. The code shown was like attacking Fermat's last theorem with a little Python script checking out number triplets. It's already been done (not to mention that that theorem's been proven, although that's, AFAIK, not the case for Collatz'). >>> Now, it's a different story if you're using the gmpy module. You DON'T >>> want to use literals in loops involving gmpy, because they would have >>> to be coerced to .mpz's on every pass through the loop. > [...] >> Yeah, good point. Few languages have compile time evaluation of >> logically constant expressions. > > Surely that's an implementation issue rather than a language issue. No, it isn't. An optimizer can only do so much, as you yourself note below! With language support it's a very different matter because guarantees propagate so that sophisticated analysis is no longer necessary: the compiler /knows/, because it's explicitly being told. >> C++0x will have that feature (called >> 'constexpr' IIRC) but in Python, current C++ etc. it's just a good idea >> to precompute values, and name them, rather than computing them again >> and again where they're needed. > > CPython 2.5 and on has a keyhole optimizer that replaces many constant > expressions with pre-computed values. > > # Python 2.4 >>>> dis.dis(compile('1+1', '', 'eval')) > 0 0 LOAD_CONST 0 (1) > 3 LOAD_CONST 0 (1) > 6 BINARY_ADD > 7 RETURN_VALUE > > # Python 2.5 >>>> dis.dis(compile('1+1', '', 'eval')) > 1 0 LOAD_CONST 1 (2) > 3 RETURN_VALUE > > > Unfortunately it doesn't help Mensanator's case, because there's no way > to tell the compiler to generate mpz objects instead of int objects, and > expressions such as gmpy.mpz(0) are not recognised as compile-time > constants. See? ;-) >>> Mine does when I use gmpy. Otherwise, the notion that "most names are >>> constants" is generally false. >> No, it depends on what you mean by "constant". > > All names are constant. Always. The Python language does not support > renaming names -- as far as I know, no language does. No-ones been talking about renaming names. I think that's purely rhetorical on your part but it may be that you really believe so. In the latter case, just try to interpret statements so that they're meaningful instead of meaningless. :-) >> The problem with Python, >> as Google noted, is that the language is so excessively dynamic: even >> names of routines are variables, > > Don't say that, that is confusing the name with the value. Nope. > The terms > "constant" and "variable" refer to the values bound to a name, not the > name itself: I'm sorry, that's incorrect. Quote from §4.1 "Naming and binding" of the Python 3.1.1 language spec: "If a name is bound in a block, it is a local variable of that block, unless declared as nonlocal. If a name is bound at the module level, it is a global variable. (The variables of the module code block are local and global.) If a variable is used in a code block but not defined there, it is a free variable." > what you mean is that even routines are variables. I'm sorry but I can't make sense of what you write here. In addition I'm not sure what you mean because there are two main interpretations. If you mean that user defined Python routines are mutable, yes that's right, but not what I was talking about (which you can easily see by checking whether it makes sense in context; it doesn't). If you mean that a routine of itself is a variable, no it isn't, but the name of a routine, like "foo" in def foo: print( "uh" ) or "bar" in bar = lambda: print( "oh" ) is a variable, per the language specification's definition quoted above (and also by any reasonable meaning of "variable"!). The meaning of "variable" for Python terminology is specified by the language specification, as quoted above: a variable is a name. [snipped rest, irrelevant] Cheers & hth., - Alf
From: Steven D'Aprano on 18 Dec 2009 22:36 On Fri, 18 Dec 2009 15:26:05 -0800, Mensanator wrote: >> The second deviation is that since most names are constants, > > Really? Does that mean you don't use literals, to save the time required > to convert them to integers? Isn't that done at compile time? > > So, instead of doing the Collatz Conjecture as > > while a>1: > f = gmpy.scan1(a,0) > if f>0: > a = a >> f > else: > a = a*3 + 1 > > You would do this? > > zed = 0 > one = 1 > two = 2 > twe = 3 > while a>one: > f = gmpy.scan1(a,zed) > if f>zed: > a = a >> f > else: > a = a*twe + one > > Does this really save any time? There are some people who might argue that using *any* magic constants in code is wrong, and that *all* such values should be declared as a constant. It's easy to take the mickey out of such an extreme position: zed = 0 # in case we need to redefine 0 as something else one = 1 # likewise two = 3 # changed from 2 to 3 to reflect the end of the Mayan calendar # The following is guaranteed to pass unless the world is ending. assert one+one == two-zed -- Steven
|
Next
|
Last
Pages: 1 2 3 Prev: Solaris 2.6 boot errors Next: Programming intro book ch1 and ch2 (Windows/Python 3) - Request For Comments |