7

Right now I have this class:

class foo():
  def __init__(self):
      self.l = []

Right now, I can set a variable to foo without an argument in the parameter because it doesn't take one, but how can I allow this continue to take no required parameters, but also put in a list if I wanted into foo()? Example:

>>> f = foo([1,2,3]) #would be legal and
>>> f = foo() # would be legal

3 Answers 3

14
def __init__(self, items=None):
    if items is None: items = []
    self.l = items

In response to @Eastsun's edit, I propose a different structure to __init__

def __init__(self, items=()):
    ''' Accepts any iterable 
    The appropriate TypeError will be raised if items is not iterable '''
    self.l = list(items)

Note that lowercase l is a bad name, it can be confused with 1

Sign up to request clarification or add additional context in comments.

5 Comments

The second solution is much more beautiful than mine.
No, putting mutable objects as default values is not recommended. THe first one, checking for None, is the best and idiomatic method.
@keith Does it matter if items mutable or not in this case? Since items could never be modified in anywhere. Or it just about code style?
It's not just style. The list is a global object and persists in the module. Using a list (or a tuple) in that way only does a shallow copy. Any other mutable object contained in the list may be potentially access and modified in unexpected ways. It's a bad practice. Using None as default and checking "is None: then ..." is the better practice.
@Keith nope it was an empty list
8
def __init__(self, items=None):
    self.l = items or []

Or

def __init__(self, items=None):
    self.l = items if items else []

Edit in response to Dougal's comment. (I have been learning Python about two weeks, so here is just my personal opinion. Correct me if I am wrong.) In a programming language like python, it is hard to prevent someone passing an unwanted type of object to your function or method. In my idea, the security way to assure the __init__ always work is like this:

def __init__(self, items = None):
    if isinstance(items, Iterable):
        self.l = list(items)
    elif items is None:
        self.l = []
    else:
        raise TypeError('items must be iterable')

Note: the above method always make a shallow copy if items is already a list.

6 Comments

I've gotten out of the habit of converting arbitrary objects to booleans, because it'll generally cause an exception with numpy arrays. Of course, if you don't use numpy this isn't an issue, but I generally prefer to explicitly check is None.
@Dougal Yes, you are right. jamylak 's code is more clear than mine. I am just tend to write shorter codes sometimes.
@Eastsun Your code in the edit addresses a different problem than the one I was talking about. In general, I'm mostly fine with things breaking in strange ways if you use the API wrong, though it depends on the use case of your code. I'm just pointing out that I used to frequently use implicit conversions to booleans, but that has bit me more than once now that I work with numpy arrays so frequently, which don't support that operation because it's kind of ambiguous.
@Dougal I am about to learn numpy. I have tried xs = numpy.array([1]); ys = numpy.array([]); zs = ys or xs, it seems worked fine.
Now try numpy.array([1, 1]) or True. You happened to pick the one example where it does work. :)
|
-1
class foo():
  def __init__(self, items=[]):
      self.l = items

3 Comments

Try a = foo(); b = foo(); a.l.append(1). Then b.l == [1]. Mutable objects as default arguments are a Bad Idea™ unless you're absolutely sure it's okay.
Yes do not do this... remember that default arguments are created at the functions definition, not at runtime. Therefore each function uses the same items
By each function I meant each function run

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.