Python FAQs

Python 官方文档

Glossary

关于 Glossary 更多内容请见 Glossary

What is the difference between arguments and parameters?

这个是在官方文档 FAQ 部分的,但是跟下面 的 argument 有关系,所以也放这。

Parameters are defined by the names that appear in a function definition, whereas arguments are the values actually passed to a function when calling it. Parameters define what types of arguments a function can accept. For example, given the function definition:

def func(foo, bar=None, **kwargs):
    pass

foo, bar and kwargs are parameters of func. However, when calling func, for example:

func(42, bar=314, extra=somevar)

the values 42, 314, and somevar are arguments.

argument

关于 keyword argument 和 positional argument 更多内容请见Positional and Keyword Arguments

A value passed to a function (or method) when calling the function. There are two kinds of argument:

  • keyword argument: an argument preceded by an identifier (e.g. name=) in a function call or passed as a value in a dictionary preceded by **. For example, 3 and 5 are both keyword arguments in the following calls to complex():
complex(real=3, imag=5)
complex(**{'real': 3, 'imag': 5})
  • positional argument: an argument that is not a keyword argument. Positional arguments can appear at the beginning of an argument list and/or be passed as elements of an iterable preceded by *. For example, 3 and 5 are both positional arguments in the following calls:
complex(3, 5)
complex(*(3, 5))

Arguments are assigned to the named local variables in a function body. See the Calls section for the rules governing this assignment. Syntactically, any expression can be used to represent an argument; the evaluated value is assigned to the local variable.

FAQs

Python 官方文档的 FAQ 的版块在这里 Programming FAQ

Why are default values shared between objects?

这个问题很重要,值得研究!
下面的代码例子中,容易造成 bug 的 代码中 有参数默认值。
参数默认值是一个空的 dictionary。
调用该函数,函数体内部修改 dict 的 item。
会导致每次新调用,该默认参数指向的 list 会保留原有的 item,并且增加新的 item。


新手程序员常常中招这类 Bug。请看以下函数:

def foo(mydict={}):  # Danger: shared reference to one dict for all calls
    ... compute something ...
    mydict[key] = value
    return mydict

第一次调用此函数时, mydict 中只有一个数据项。第二次调用 mydict 则会包含两个数据项,因为 foo() 开始执行时, mydict 中已经带有一个数据项了。

大家往往希望,函数调用会为默认值创建新的对象。但事实并非如此。默认值只会在函数定义时创建一次。如果对象发生改变,就如上例中的字典那样,则后续调用该函数时将会引用这个改动的对象。

按照定义,不可变对象改动起来是安全的,诸如数字、字符串、元组和 None 之类。而可变对象的改动则可能引起困惑,例如字典、列表和类实例等。

因此,不把可变对象用作默认值是一种良好的编程做法。而应采用 None 作为默认值,然后在函数中检查参数是否为 None 并新建列表、字典或其他对象。例如,代码应如下所示:

def foo(mydict={}):
    ...

but

def foo(mydict=None):
    if mydict is None:
        mydict = {}  # create a new dict for local namespace

参数默认值的特性有时会很有用处。
如果有个函数的计算过程会比较耗时,有一种常见技巧是将每次函数调用的参数和结果缓存起来,并在同样的值被再次请求时返回缓存的值。这种技巧被称为“memoize”,实现代码可如下所示:

# Callers can only provide two parameters and optionally pass _cache by keyword
def expensive(arg1, arg2, *, _cache={}):
    if (arg1, arg2) in _cache:
        return _cache[(arg1, arg2)]

    # Calculate the value
    result = ... expensive computation ...
    _cache[(arg1, arg2)] = result           # Store result in the cache
    return result

也可以不用参数默认值来实现,而是采用全局的字典变量;这取决于个人偏好。

Why did changing list ‘y’ also change list ‘x’?

来自 copy — Shallow and deep copy operations 的引用

Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.

注意,赋值生成的 variable 并不是一个 object。只是指向 object 的一个 reference。
如果原来的 object 是 mutable 的,比如 dict、list 等,那么如果有多个 variable 指向它,则通过其中一个 variable 修改了 object,通过其他 variable 来获取该 object 值时,会发现输出的值也改变了。

但是如果原来的 object 是 immutable 的,则通过其中一个 variable 修改 object时,通过其他 variable 访问该 object时,发现没有变。因为修改 object 的 variable 是指向了一个新的 object。但是其他 variable 指向的还是原先的 object。

If you wrote code like:

>>> x = []
>>> y = x
>>> y.append(10)
>>> y
[10]
>>> x
[10]

you might be wondering why appending an element to y changed x too.

There are two factors that produce this result:

Variables are simply names that refer to objects. Doing y = x doesn’t create a copy of the list – it creates a new variable y that refers to the same object x refers to. This means that there is only one object (the list), and both x and y refer to it.

Lists are mutable, which means that you can change their content.

After the call to append(), the content of the mutable object has changed from [] to [10]. Since both the variables refer to the same object, using either name accesses the modified value [10].

If we instead assign an immutable object to x:

>>> x = 5  # ints are immutable
>>> y = x
>>> x = x + 1  # 5 can't be mutated, we are creating a new object here
>>> x
6
>>> y
5

How do I copy an object in Python?

关于 copy.copy() or copy.deepcopy() 区别的讨论,看最高赞:
What is the difference between shallow copy, deepcopy and normal assignment operation?

来自 copy — Shallow and deep copy operations 的内容:

The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):

  • A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
  • A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

In general, try copy.copy() or copy.deepcopy() for the general case. Not all objects can be copied, but most can.

Some objects can be copied more easily.
Dictionaries have a copy() method:

newdict = olddict.copy()

Sequences can be copied by slicing:

new_l = l[:]

How can I pass optional or keyword parameters from one function to another?

Collect the arguments using the * and ** specifiers in the function’s parameter list; this gives you the positional arguments as a tuple and the keyword arguments as a dictionary. You can then pass these arguments when calling another function by using * and **:

def f(x, *args, **kwargs):
    ...
    kwargs['width'] = '14.3c'
    ...
    g(x, *args, **kwargs)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

培之

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值