且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

* args是将参数传递给装饰函数或从装饰函数传递参数的正确方法吗?

更新时间:2023-10-21 22:30:04

装饰器的编写方式 do_stuff_load_only 可以使用常规参数进行定义,即使您实际上并没有传递参数当你打电话的时候.这是因为名称 do_stuff_load_only 不会绑定到一个参数的函数.它将绑定到 load_db 内部定义的 zero 参数函数 wrapper . wrapper 本身将负责将参数传递给要修饰的实际单参数函数.

The way your decorator is written, do_stuff_load_only can be defined with a regular parameter, even if you won't actually pass an argument when you call it. That's because the name do_stuff_load_only isn't going to be bound to a one-argument function; it's going to be bound to the zero-argument function wrapper defined inside load_db. wrapper itself will take care of passing an argument to the actual one-argument function being decorated.

@load_db
def do_stuff_load_only(db):
    # a function that just consumes the DB, without changing it
    print(f"initial DB is {db}")


do_stuff_load_only()

定义 do_stuff_load_only(* db)将有效,但会更改与 db 实际绑定的内容;在这种情况下,它将是单例元组(5,),而不是整数 5 .

Defining do_stuff_load_only(*db) would work, but changes what is actually bound to db; in this case, it would be the singleton tuple (5,) rather than the integer 5.

如果您认为这看起来很尴尬,那是因为. load_db 具有隐藏"状态,您不必担心的副作用.上下文管理器可能更适合这里:

If you think this looks awkward, that's because it is. load_db has a "hidden" side effect that you shouldn't have to worry about. A context manager would probably be more fitting here:

from contextlib import contextmanager


@contextmanager
def load_db():
    print("Initializing the database")
    yield 5  # provide it
    print("Tearing down the database")


def do_stuff_load_only(*db):
    # a function that just consumes the DB, without changing it
    print(f"initial DB is {db}")


with load_db() as db:
    do_stuff_load_only(db)

现在绑定到 do_stuff_load_only 的函数的定义和使用与上下文管理器隐藏数据库的创建和销毁方式有关.上面代码的输出是

Now the definition and use of the function bound to do_stuff_load_only agree, with the details of how the database is created and destroyed hidden by the context manager. The output of the above code is

Initializing the database
initial DB is 5
Tearing down the database