Re: share function argument between subsequent calls but not between class instances!

2006-02-21 Thread Duncan Booth
Steven D'Aprano wrote:

>>> The most common idiom for such a marker is the None value.
>>> 
>> 
>> Can you provide any firm evidence that using None is more common?
> 
> 
> Yes, I wrote a quick and dirty script to roughly count the default
> values in the Python 2.3 standard library. Here are my results:
> 
> $ python default_counter.py
> 185 .py source files were opened.
> 4437 function or method definitions were found.
> These functions included at least 1228 arguments with default values.
> 529 or 4.307818e+01% used None as the default value.
> 
> So, roughly 40% of default values in the standard library are None. 

Fair enough, although I would point out that you haven't made any attempt 
to distinguish those cases where None is being used as a marker from the 
cases where it is being used as a value in its own right or a flag to 
control the function logic.

The marker cases do seem to be the most common but there are plenty of 
other cases:

e.g. base64.b64encode & base64.b64decode avoid part of the code if passed 
None, but don't actually substitute another value in place of the default.

cgi.FieldStorage has methods getvalue, getfirst where the default=None is 
simply that: the default to be returned. The make_file method has a 
defaulted argument which it doesn't use at all.

Also, most of the standard library predates a time when you could create a 
unique marker value just by calling 'object()'. When it was written None 
was by far the simplest option even in cases where a separate marker value 
might have been more appropriate.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: share function argument between subsequent calls but not between class instances!

2006-02-20 Thread Steven D'Aprano
On Mon, 20 Feb 2006 08:52:09 +, Duncan Booth wrote:

> Ben Finney wrote:
> 
>> Duncan Booth <[EMAIL PROTECTED]> writes:
>>> If you intend to only use the default some of the time, and at other
>>> times pass in a different list, then save the 'default' in the
>>> instance and use a special marker value to indicate when you intend
>>> the default to be used:
>> 
>> The most common idiom for such a marker is the None value.
>> 
> 
> Can you provide any firm evidence that using None is more common?


Yes, I wrote a quick and dirty script to roughly count the default
values in the Python 2.3 standard library. Here are my results:

$ python default_counter.py
185 .py source files were opened.
4437 function or method definitions were found.
These functions included at least 1228 arguments with default values.
529 or 4.307818e+01% used None as the default value.

So, roughly 40% of default values in the standard library are None. If I
cared enough (I don't) I would re-write the counter to analyse all the
default values. But by eye-balling the function lines, the impression I
get is that the remaining 60% of default values are divided unequally
between dozens of different defaults. Some random examples:

"rb", "", "Prompt: ", -1, 0, 1, 3, sys.maxint, (), [].

My gut-feeling would be, 40-odd percent None, 40-odd percent for small
ints (-1, 0, 1, ..?), the remainder split between everything else.

If anyone cares to look at my quick and dirty source code, it is attached
following my signature.


-- 
Steven.




* * * 

"""Rough and ready script to analyse the Python standard library 
and count function definitions that use None as a default argument.
"""

from __future__ import division
import os

location = "/usr/lib/python2.3/"

file_count = 0  # number of files successfully opened
func_count = 0  # number of function definitions
default_count = 0  # number of functions with a default value
none_count = 0  # number of functions with None as a default value

for name in os.listdir(location):
if name.endswith(".py") and os.path.isfile(location+name):
try:
fp = file(location+name, "r")
except IOError:
continue
file_count += 1
lines = fp.readlines()
fp.close()
for line in lines:
line = line.strip()
if line.startswith("#"):
continue
elif line.startswith("def "):
func_count += 1
default_count += line.count("=")
none_count += line.count("None")
# if line.count("="): print line

# Report results found:

print "%d .py source files were opened." % file_count
print "%d function or method definitions were found." % func_count
print "These functions included at least %d arguments with default values." % 
default_count
print "%d or %e%% used None as the default value." % \
(none_count, none_count/default_count*100)


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


Re: share function argument between subsequent calls but not between class instances!

2006-02-20 Thread Duncan Booth
Ben Finney wrote:

> Duncan Booth <[EMAIL PROTECTED]> writes:
>> If you intend to only use the default some of the time, and at other
>> times pass in a different list, then save the 'default' in the
>> instance and use a special marker value to indicate when you intend
>> the default to be used:
> 
> The most common idiom for such a marker is the None value.
> 

Can you provide any firm evidence that using None is more common?

Both uses are common. Use whichever you are happier with (except of course 
in the case where None is a potential value distinct from the default).
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: share function argument between subsequent calls but not between class instances!

2006-02-18 Thread Ben Finney
Duncan Booth <[EMAIL PROTECTED]> writes:
> If you intend to only use the default some of the time, and at other
> times pass in a different list, then save the 'default' in the
> instance and use a special marker value to indicate when you intend
> the default to be used:

The most common idiom for such a marker is the None value.

class Test(object):
def __init__(self):
self.L = []
def f(self, a, L=None):
if L is None:
L = self.L
L.append(a)
return L

-- 
 \"Consider the daffodil. And while you're doing that, I'll be |
  `\   over here, looking through your stuff."  -- Jack Handey |
_o__)  |
Ben Finney 
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: share function argument between subsequent calls but not between class instances!

2006-02-18 Thread Felipe Almeida Lessa
Em Sáb, 2006-02-18 às 16:50 +, Duncan Booth escreveu:
> marker = object()
> 
> class Test(object):
> def __init__(self):
> self.L = []
> 
> def f(self,a, L=marker):
> if L is marker:
> L = self.L
> L.append(a)
> return L 

As hasattr(None, "append") == False, you could also do:

class Test(object):
def __init__(self):
self.L = []

def f(self, a, L=None):
if L is None:
L = self.L
L.append(a)
return L

-- 
"Quem excele em empregar a força militar subjulga os exércitos dos
outros povos sem travar batalha, toma cidades fortificadas dos outros
povos sem as atacar e destrói os estados dos outros povos sem lutas
prolongadas. Deve lutar sob o Céu com o propósito primordial da
'preservação'. Desse modo suas armas não se embotarão, e os ganhos
poderão ser preservados. Essa é a estratégia para planejar ofensivas."

  -- Sun Tzu, em "A arte da guerra"

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

Re: share function argument between subsequent calls but not between class instances!

2006-02-18 Thread Duncan Booth
K. Jansma wrote:

> as you can see, the b.f method shares L with a.f.
> How can I avoid this without using eg. self.L in an __init__?
> 

You cannot.

If a method argument has a default value then the same default is used 
whenever the method is called. If you want each instance to have its own 
value then you must use an attribute on the instance.

If you intend to only use the default some of the time, and at other times 
pass in a different list, then save the 'default' in the instance and use a 
special marker value to indicate when you intend the default to be used:

marker = object()

class Test(object):
def __init__(self):
self.L = []

def f(self,a, L=marker):
if L is marker:
L = self.L
L.append(a)
return L
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: share function argument between subsequent calls but not between class instances!

2006-02-18 Thread Felipe Almeida Lessa
Em Sáb, 2006-02-18 às 17:42 +0100, K. Jansma escreveu:
> How can I avoid this without using eg. self.L in an __init__?

Why not use it? That's how it's meant to be done!

> Thanks in advance,
> Karel.

Cya,
Felipe.

-- 
"Quem excele em empregar a força militar subjulga os exércitos dos
outros povos sem travar batalha, toma cidades fortificadas dos outros
povos sem as atacar e destrói os estados dos outros povos sem lutas
prolongadas. Deve lutar sob o Céu com o propósito primordial da
'preservação'. Desse modo suas armas não se embotarão, e os ganhos
poderão ser preservados. Essa é a estratégia para planejar ofensivas."

  -- Sun Tzu, em "A arte da guerra"

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

share function argument between subsequent calls but not between class instances!

2006-02-18 Thread K. Jansma
Hi,

given the following example class

class Test:
def f(self,a, L=[]):
L.append(a)
return L

and the following statements

a = Test()
a.f(0)
a.f(0)
a.f(0)
b = Test()
b.f(0)

this is the output I would like to have (i.e., expect)

>>> a = Test()
>>> a.f(0)
[0]
>>> a.f(0)
[0, 0]
>>> a.f(0)
[0, 0, 0]
>>> b = Test()
>>> b.f(0)
[0]

But this is what I get:

>>> a = Test()
>>> a.f(0)
[0]
>>> a.f(0)
[0, 0]
>>> a.f(0)
[0, 0, 0]
>>> b = Test()
>>> b.f(0)
[0, 0, 0, 0]


as you can see, the b.f method shares L with a.f.
How can I avoid this without using eg. self.L in an __init__?

Thanks in advance,
Karel.

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