4

I am trying to translate a Python Voronoi Generator to Java but I am not very familiar with keyword arguments and I am confused by the keyword argument that is written as a parameter of a function.

I've read this question, but it only covers calling arguments, not defining them.

It seems like the function is just setting a and b to None. I don't understand why that is necessary. Why not just type None instead of using parameters like that?

What is the point of using keyword parameters equal to None in function definitions?

The function:

class Arc:
    p = None
    pprev = None
    pnext = None
    e = None
    s0 = None
    s1 = None

    def __init__(self, p, a=None, b=None):
        self.p = p
        self.pprev = a
        self.pnext = b
        self.e = None
        self.s0 = None
        self.s1 = None
LuminousNutria
  • 1,883
  • 2
  • 18
  • 44
  • 1
    Don't create a lot of class variables (i.e. static variables) only to immediately shadow them in `__init__` – juanpa.arrivillaga Jan 16 '19 at 16:26
  • @juanpa.arrivillaga It's not my code. – LuminousNutria Jan 16 '19 at 16:34
  • 1
    @LuminousNutria FYI: class members don't need to be declared in Python (they can be in `__slots__` but mostly aren't). the lines doing e.g. `p = None` at the top are a bit of an anti-pattern and indicative of somebody who doesn't know the language. the repo you pointed to links to a [C++ version](https://www.cs.hmc.edu/~mbrubeck/voronoi.html) that looks more idiomatic – Sam Mason Jan 16 '19 at 17:12
  • 1
    @SamMason well, and that was exactly my point. It is important to understand, not only do members not need to be declared, **there are no variable declarations in Python**, and exactly as you say, seeing code as the above makes it look like someone is writing Java/C++ in Python – juanpa.arrivillaga Jan 16 '19 at 17:45
  • @juanpa.arrivillaga Oh, I see. Thanks. I thought it looked weird too. – LuminousNutria Jan 16 '19 at 19:37
  • @juanpa.arrivillaga Yup, mostly agreed, but it's slowly changing with things like type hints. Also, `nonlocal` and `global` affects a variable's scope, and scope is pretty tied to type declarations in other languages. – Sam Mason Jan 16 '19 at 23:14
  • @SamMason type hints not really. Python is not going to become a statically typed language, and type hints change nothing about the semantics of Python. The global and nonlocal statements are close to variable declarations, but still, not really. I would call them more like "directives", since doing `global foo` doesn't create a variable `foo`, it does nothing with the identifier, it just changes the bytecode to one that checks for a global name instead of a local name – juanpa.arrivillaga Jan 16 '19 at 23:18

4 Answers4

6

Keyword arguments can have a default value. In this case, the default value of a and b are None. This means that when these arguments aren't passed into the function, a and b are set to None.

Example:

def func(a=None):
    print(a)
func()
>>>None

But if you do something like this:

def func(a):
    print(a)
func()
>>>TypeError: func() missing 1 required positional argument: 'a'
Primusa
  • 13,136
  • 3
  • 33
  • 53
2
def __init__(self, p, a=None, b=None):

That line is defining the __init__ method, which you can think of as a constructor for the class. It's not calling the method.

Setting a and b equal to None in the method definition makes None their default value. This makes them optional when you call the method. (So you can call the method with 1, 2, or 3 parameters.) If you don't pass in values for a and b, None will be used. It's common in Python to use optional parameters in place of overloading methods.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
2

This is a concept called default value.

Using this syntax, the caller can choose whether to specify a value for every such argument or use the default one.

Suppose you have a method that has a default behavior, but you want to reserve the possibility to change it willingly. This give you this power.

Consider the following example:

def custom_method(msg, prefix=None):
  tag = prefix if prefix else ''
  print(tag + msg)

Now, as a user of this API, you can choose to use a prefix, or avoid it:

custom_method('Dude', 'Hi')
# Prints 'Hi Dude'

Or:

custom_method('Dude')
# Prints 'Dude'
Daniel Trugman
  • 8,186
  • 20
  • 41
1

This is the Python syntax for default arguments, or optional argument.

Arguments which are declared with a default value, will receive that default value if they are not passed in the function call, and will receive what is passed in the other case.

Here Arc(p) is the same as Arc(p, None, None), but you could use:

a1 = Arc(p)
a2 = Arc(p, a1)

and then a2.pprev will be a1.

But there are some caveats with mutable default arguments... be careful with them or better avoid them until you are more proficient at Python.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252