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

K

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.
 
D

Duncan Booth

K. Jansma said:
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
 
F

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"
 
F

Felipe Almeida Lessa

Em Sáb, 2006-02-18 às 16:50 +0000, 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"
 
B

Ben Finney

Duncan Booth said:
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
 
D

Duncan Booth

Ben said:
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).
 
S

Steven D'Aprano

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)
 
D

Duncan Booth

Steven said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top