gpt4 book ai didi

Python 用可变数量的位置参数和可选参数装饰方法

转载 作者:太空狗 更新时间:2023-10-30 01:14:25 24 4
gpt4 key购买 nike

我正在使用 SQLalchemy 编写我的第一个 Python (3.4) 应用程序。我有几种方法,它们的模式都非常相似。它们采用可选参数 session,默认为 None。如果传递了 session,该函数将使用该 session ,否则它会打开并使用一个新 session 。例如,考虑以下方法:

def _stocks(self, session=None):
"""Return a list of all stocks in database."""
newsession = False
if not session:
newsession = True
session = self.db.Session()
stocks = [stock.ticker for stock in session.query(Stock).all()]
if newsession:
session.close()
return stocks

因此,作为 Python 的新手并渴望了解它的所有功能,我认为现在是学习一些有关 Python 装饰器的知识的最佳时机。所以经过大量阅读,像这样this series of blog poststhis太棒了所以回答,我写了以下装饰器:

from functools import wraps

def session_manager(func):
"""
Manage creation of session for given function.

If a session is passed to the decorated function, it is simply
passed through, otherwise a new session is created. Finally after
execution of decorated function, the new session (if created) is
closed/
"""
@wraps(func)
def inner(that, session=None, *args, **kwargs):
newsession = False
if not session:
newsession = True
session = that.db.Session()
func(that, session, *args, **kwargs)
if newsession:
session.close()
return func(that, session, *args, **kwargs)
return inner

而且看起来效果很好。原来的方法现在简化为:

@session_manager
def _stocks(self, session=None):
"""Return a list of all stocks in database."""
return [stock.ticker for stock in session.query(Stock).all()]

但是,当我将装饰器应用到一个除了可选的 session 之外还接受一些位置参数的函数时,我得到了一个错误。所以试着写:

@session_manager
def stock_exists(self, ticker, session=None):
"""
Check for existence of stock in database.

Args:
ticker (str): Ticker symbol for a given company's stock.
session (obj, optional): Database session to use. If not
provided, opens, uses and closes a new session.

Returns:
bool: True if stock is in database, False otherwise.
"""
return bool(session.query(Stock)
.filter_by(ticker=ticker)
.count()
)

并像 print(client.manager.stock_exists('AAPL')) 一样运行会给出一个 AttributeError 并具有以下回溯:

Traceback (most recent call last):
File "C:\Code\development\Pynance\pynance.py", line 33, in <module>
print(client.manager.stock_exists('GPX'))
File "C:\Code\development\Pynance\pynance\decorators.py", line 24, in inner
func(that, session, *args, **kwargs)
File "C:\Code\development\Pynance\pynance\database\database.py", line 186, in stock_exists
.count()
AttributeError: 'NoneType' object has no attribute 'query'
[Finished in 0.7s]

所以我根据回溯猜测,我弄乱了参数的顺序,但我不知道如何正确地排序它们。除了 session 之外,我还有一些我想要修饰的函数,它们可以接受 0-3 个参数。有人可以指出我方法中的错误吗?

最佳答案

改变

def inner(that, session=None, *args, **kwargs):

def inner(that, *args, session=None, **kwargs):

return func(that, session, *args, **kwargs)

return func(that, *args, session=session, **kwargs)

有效:

def session_manager(func):

def inner(that, *args, session=None, **kwargs):
if not session:
session = object()
return func(that, *args, session=session, **kwargs)

return inner


class A():

@session_manager
def _stocks(self, session=None):
print(session)
return True

@session_manager
def stock_exists(self, ticker, session=None):
print(ticker, session)
return True

a = A()
a._stocks()
a.stock_exists('ticker')

输出:

$ python3 test.py
<object object at 0x7f4197810070>
ticker <object object at 0x7f4197810070>

当您使用 def inner(that, session=None, *args, **kwargs) 时,任何第二个位置参数(包括 self)都被视为 session 参数。因此,当您调用 manager.stock_exists('AAPL') 时,session 获取值 AAPL

关于Python 用可变数量的位置参数和可选参数装饰方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30696050/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com