Non-Standard Optional Argument Defaults

别等时光非礼了梦想. 提交于 2019-12-10 16:27:43

问题


I have two functions:

def f(a,b,c=g(b)):
    blabla

def g(n):
    blabla

c is an optional argument in function f. If the user does not specify its value, the program should compute g(b) and that would be the value of c. But the code does not compile - it says name 'b' is not defined. How to fix that?

Someone suggested:

def g(b):
    blabla

def f(a,b,c=None):
    if c is None:
        c = g(b)
    blabla

But this doesn't work. Maybe the user intended c to be None and then c will have another value.


回答1:


def f(a,b,c=None):
    if c is None:
        c = g(b)

If None can be a valid value for c then you do this:

sentinel = object()
def f(a,b,c=sentinel):
    if c is sentinel:
        c = g(b)



回答2:


You cannot do it that way.

Inside the function, check if c is specified. If not, do the calculation.

def f(a,b,c=None):
    if c == None:
        c = g(b)
    blabla



回答3:


value of c will be evaluated (g(b)) at compilation time. You need g defined before f therefore. And of course you need a global b variable to be defined at that stage too.

b = 4

def g(a):
    return a+1

def test(a, c=g(b)):
    print(c)

test(b)

prints 5.




回答4:


The problem with

sentinel = object()
def f(a, b, c=sentinel):
  if c is sentinel:
    c = g(b)

is that sentinel is global/public unless this code is part of a function/method. So someone might still be able to call f(23, 42, sentinel). However, if f is global/public, you can use a closure to make sentinel local/private so that the caller cannot use it:

def f():
  sentinel = object()
  def tmp(a, b, c=sentinel):
    if c is sentinel:
      c = g(b)
  return tmp
f = f()

If you are concerned that static code analyzers could get the wrong idea about f then, you can use the same parameters for the factory:

def f(a, b, c=object()): #@UnusedVariable
  sentinel = object()
  def tmp(a, b, c=sentinel):
    if c is sentinel:
      c = g(b)
  return tmp
f = f(23, 42)



回答5:


def f(a,b,*args):
    if len(args) == 1:
        c = args[0]
    elif len(args) == 0:
        c = g(b)
    else:
        raise Exception('Function takes 2 or 3 parameters only.')
    blabla

def g(n):
    blabla

You can probably structure it better, but that's the main idea. Alternatively you can use **kwargs and use the function like f(a,b,c=Something), you just have to modify f accordingly.

Documentation



来源:https://stackoverflow.com/questions/1118454/non-standard-optional-argument-defaults

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!