Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python3.9上是否有关于Typing.Optional的更新,还是我做错了什么?_Python_Discord.py - Fatal编程技术网

在Python3.9上是否有关于Typing.Optional的更新,还是我做错了什么?

在Python3.9上是否有关于Typing.Optional的更新,还是我做错了什么?,python,discord.py,Python,Discord.py,当我在Discord.py中为我的bot编写帮助命令时,这个函数并没有像我预期的那样工作 def syntax(command): cmd_and_aliases = '|'.join([str(command), *command.aliases]) params = [] for key, value in command.params.items(): if key not in ('self', 'ctx'): params

当我在Discord.py中为我的bot编写帮助命令时,这个函数并没有像我预期的那样工作

def syntax(command):
    cmd_and_aliases = '|'.join([str(command), *command.aliases])
    params = []
    for key, value in command.params.items():
        if key not in ('self', 'ctx'):
            params.append(f'[{key}]' if 'NoneType' in str(value) else f'<{key}>')
    params = ' '.join(params)
    return f'`{cmd_and_aliases} {params}`'
例如,对于该命令,结果如下所示

slap|hit <Member> [reason]
slap | hit[原因]
但我最终得到的是:

slap|hit <Member> <reason>.
slap | hit。
我是否做错了什么,或者是否有任何更新会导致此功能中断? 如果我做错了什么,请帮助我,说明我能做些什么。

为什么 这种行为在3.9中确实发生了变化;我相信这就是原因。看起来这些变化是从commit开始的,但我相信您的特定问题的表现是由于前者

我对
打字
模块的管道不太熟悉,但据我所知,
可选
的表示现在是特殊情况,返回原样,即
打字。可选[x]
而不是“扩展”到
打字。联合[x,非类型]
。但是,它们仍然具有相同的“类型”,但这里重要的一点是,它们的“类型”已更改为,其
\uuuu repr\uuu
为:

def __repr__(self):
    args = self.__args__
    if len(args) == 2:
        if args[0] is type(None):
            return f'typing.Optional[{_type_repr(args[1])}]'
        elif args[1] is type(None):
            return f'typing.Optional[{_type_repr(args[0])}]'
    return super().__repr__()
可能的解决方案 首先,我想指出,您可以使用而不是
command.params
(据我所知,奇怪的是,它没有文档记录)。它的功能相同,只是它会自动排除
self
ctx
,因此您不必检查它。我将在下面的解决方案中使用它

N.B.
clean_params
将参数作为对象返回,因此我们有一个额外的层

我想出了两个可能的解决办法。第一个与您的非常接近,因为我们对键入的
进行简单的字符串检查。可选的

for key, value in command.clean_params.items():
    optional = str(value.annotation).startswith('typing.Optional')
    params.append(f'[{key}]' if optional else f'<{key}>')
对于键,command.clean_params.items()中的值:
optional=str(value.annotation).startswith('typing.optional')
params.append(如果可选,则为f'[{key}]',否则为f')
现在我个人不喜欢在确定类型时进行字符串检查(在本例中为泛型),所以我会选择一些不同的东西。如中所述,我们可以对泛型进行运行时内省,所以让我们利用它

for key, value in command.clean_params.items():
    anno = value.annotation
    try:
        optional = anno.__origin__ is Union and anno.__args__[1] is type(None)
    except AttributeError:
        optional = False
    params.append(f'[{key}]' if optional else f'<{key}>')
对于键,command.clean_params.items()中的值:
anno=value.annotation
尝试:
可选=anno.\uuuuu origin\uuuuuu是并集,anno.\uuuuu args\uuuuuu[1]是类型(无)
除属性错误外:
可选=错误
params.append(如果可选,则为f'[{key}]',否则为f')

这种方法的另一个好处是它可以在Python3.8中工作(我认为也是3.7),而字符串检查版本显然只能在3.9中工作。您可以利用
sys.version\u info
进行多个字符串检查,但相比之下,这似乎太麻烦了。

尝试了您得到的两个建议。第一个并没有解决问题。它的工作原理与原始代码相同。有趣的是,您得到的
str(value)
的值是多少?第二种方法呢?嗯…我忘了说第二部分了。我的错。第二部分出现了一个错误,名为:AttributeError:“Parameter”对象没有属性“origin”,我将链接尝试第二种解决方案时收到的整个错误消息:在看到您的评论后,我想“为什么我没有首先检查str(value)”,然后继续执行此操作。str(value)是“key:type”的格式。所以,可选部分类似于'key:Optional[type]',所以,我只是将
params.append(如果str(value)else f''中的'NoneType',则为f'[{key}]')
中的NoneType改为Optional,解决了这个问题。谢谢你的帮助。但是,我还是想知道如何使用你给我的第二个解决方案来解决这个问题。因为我对编码了解得越多,我就越擅长。啊,我错过了文档中关于
clean_params
的部分,它说它返回
OrderedDict[str,inspect.Parameter]
<代码>参数
来自库,用于对对象进行自省。我会更新答案以考虑到这一点。对不起,你能试着把这一点缩减到问题的要点吗?看起来大部分部件都是用来处理discord包装器的。我是否正确地阅读了您的代码/问题,即您正在尝试根据类型的字符串表示形式格式化类型,并且Optional似乎已从表示为并集更改为其他形式?
for key, value in command.clean_params.items():
    optional = str(value.annotation).startswith('typing.Optional')
    params.append(f'[{key}]' if optional else f'<{key}>')
for key, value in command.clean_params.items():
    anno = value.annotation
    try:
        optional = anno.__origin__ is Union and anno.__args__[1] is type(None)
    except AttributeError:
        optional = False
    params.append(f'[{key}]' if optional else f'<{key}>')