PyCharm 代码完成和动态转换

问题描述 投票:0回答:1

我对 Python 3 和类型提示还很陌生,我想知道是否可以在 PyCharm 或其他 IDE 中执行此操作。

例子

这是代码的简化示例。

import dataclasses
from typing import Type

@dataclasses.dataclass()
class BasePlugin:
    version: str
    arguments: str = None

@dataclasses.dataclass()
class PythonPlugin(BasePlugin):
    version: str = 3.7
    script: str = None

@dataclasses.dataclass()
class MayaPlugin(BasePlugin):
    version: str = 2022
    scene_file: str = None
    script_job: str = None


class Job:
    def __init__(self, plugin: Type[BasePlugin]):
        self.options = plugin()


job_a = Job(plugin=PythonPlugin)

理想情况下,我希望能够创建

Job
的实例并使用点符号来修改
options
字段。
例如
job_a.options.script = 'c:\test\do_stuff.py'

问题

不正确的结果

使用输入类型提示,代码完成仅显示基类的可用属性。

代码示例:

class Job:
    def __init__(self, plugin: Type[BasePlugin]):
        self.options = plugin()


job_a = Job(plugin=PythonPlugin)
job_a.options.

结果:Code completion with input type-hint


不正确的结果

没有类型提示,代码完成不会像预期的那样显示任何内容。

代码示例:

class Job:
    def __init__(self, plugin):
        self.options = plugin()


job_a = Job(plugin=PythonPlugin)
job_a.options.

结果:Code completion without input type-hint


想要的结果

我想要的是我在实例化时提供的特定子类的代码完成。 在下面的示例中,我用插件覆盖

self.options
以显示所需的结果。

代码示例:

class Job:
    def __init__(self, plugin: Type[BasePlugin]):
        self.options = PythonPlugin()  # Overriding to simulate the desired result.


job_a = Job(plugin=PythonPlugin)
job_a.options.

结果:Code completion as desired

解决方案

  1. 传参是否可以达到预期的效果?
  2. 如果没有,我唯一的其他选择是将工作类型子类化吗?
class Job:
    options: BasePlugin
    ...

class PythonJob(Job):
    options: PythonPlugin = PythonPlugin()
    ...

class MayaJob(Job):
    options: MayaPlugin = MayaPlugin()
    ...

  1. 我需要考虑的任何其他选项/示例吗?

非常感谢任何帮助。

python python-3.x pycharm type-hinting code-completion
1个回答
0
投票

您可以使用 TypeVars 和泛型来做到这一点:

import dataclasses
from typing import Generic, Type, TypeVar

BP = TypeVar("BP")

@dataclasses.dataclass()
class BasePlugin:
    version: str
    arguments: str = None

@dataclasses.dataclass()
class PythonPlugin(BasePlugin):
    version: str = 3.7
    script: str = None

@dataclasses.dataclass()
class MayaPlugin(BasePlugin):
    version: str = 2022
    scene_file: str = None
    script_job: str = None


class Job(Generic[BP]):
    def __init__(self, plugin: Type[BP]):
        self.options: BP = plugin()


job_a = Job(plugin=PythonPlugin)
job_a.options.script  # auto-completes

job_b = Job(plugin=MayaPlugin)
job_b.options.scene_file  # auto-completes
© www.soinside.com 2019 - 2024. All rights reserved.