V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
dwadewyp
V2EX  ›  Python

一个关于 Python 反射运用的问题

  •  
  •   dwadewyp · 2021-01-15 18:51:02 +08:00 · 2420 次点击
    这是一个创建于 1408 天前的主题,其中的信息可能已经有所发展或是发生改变。

    新建一个 python 的 package,在 package 中创建了一个 Animal.py 的文件,并在 Animal.py 文件中定义了一个 Animal 的类;

    ------Animal.py-------
    
    	class Animal:
    	    def __init__(self, name=None):
    	        self.name = name
    
    	    def introduce(self):
    	        pass
    
    

    与此同时在 package 下面,创建了 Dog.py,Cat.py,分别在文件中定义了 Dog,Cat 子类(均继承 Animal),并实现了 introduce 方法

    -----Dog.py--------
    
    	from animal.animal import Animal
    
    	class Dog(Animal):
    
    	    def introduce(self):
    	        print("i am a dog")
    
    ----Cat.py------
    
    	from animal.animal import Animal
    
    	class Cat(Animal):
    	    def introduce(self):
    	        print("i am a cat")
    
    
    
    • 问题:
      • 当在 package 下面定了一个很多很多继承 Animal 的文件,并且分别在文件中定义了子类; 比如 dog,cat,panda,elephant,tiger,lion, monkey.......可能会有成百上千的子类 我想输出所有的子类的 introduce() 但!!! 不可以通过重复 import 的方式引入子类然后去实例化每个子类, 我想到的是通过反射的方式去输出,但是编码无力啊。。。 有老铁能否提供些思路或者伪代码???
    15 条回复    2021-01-18 14:21:20 +08:00
    gwy15
        1
    gwy15  
       2021-01-15 18:59:19 +08:00
    Animal.__subclasses__()
    weyou
        2
    weyou  
       2021-01-15 19:08:30 +08:00 via Android
    @gwy15
    不事先 import 子类的文件,__subclasses__不会有内容
    BBrother
        3
    BBrother  
       2021-01-15 19:12:26 +08:00
    dwadewyp
        4
    dwadewyp  
    OP
       2021-01-15 19:21:31 +08:00
    @BBrother 注意是需要在不同的文件下面的哦~~~
    RickyHao
        5
    RickyHao  
       2021-01-15 19:26:11 +08:00 via Android
    你不 import,那这代码就相当于不存在吧?
    实在不行,规定个文件夹,启动的时候自动 import 文件夹下的所有代码文件
    xchaoinfo
        6
    xchaoinfo  
       2021-01-15 19:29:22 +08:00 via Android
    不引入,不实例化,ast 了解下
    maocat
        7
    maocat  
       2021-01-15 19:29:43 +08:00 via Android
    我懂题主的意思,a.py, b.py, c.py 3 个 py 文件,分别有 class A,class B(A), class C(A),比如直接运行 a.py 是不能够获取__subclasses__,因为 b.pyc.py 不在 runtime 中,可以试一试 sys.path.append(PATH)
    dwadewyp
        8
    dwadewyp  
    OP
       2021-01-16 15:09:06 +08:00
    @gwy15 @BBrother __subclasses__ 是限定在基类和子类在统一文件下, 这个题有个限定条件就是,每个子类在不同的文件中, 并且,需要在这个 animal package 外,创建一个类似 test.py 来进行处理
    dwadewyp
        9
    dwadewyp  
    OP
       2021-01-16 15:10:53 +08:00
    @BBrother 亲测 元类在 package 外层 也是不行的,
    dwadewyp
        10
    dwadewyp  
    OP
       2021-01-16 16:10:42 +08:00
    @maocat
    dir_path = os.path.abspath(os.curdir) + '/animal'

    sys.path.append(dir_path)
    亲测 也是无效
    maocat
        11
    maocat  
       2021-01-16 17:25:19 +08:00 via Android
    glob 包动态解析拿出路径,for 循环然后解析用内置 exec 方法导入,还有一种方法是 django 有个方法 impo
    rt_string 你看下源码很容易改改
    @dwadewyp
    tmackan
        12
    tmackan  
       2021-01-16 18:24:58 +08:00
    @xchaoinfo 专业
    @dwadewyp py 中有个 inspect 的反射包,但是看了下文档,没办法满足你的需求
    https://www.cnblogs.com/yaohong/p/8874154.html
    dwadewyp
        13
    dwadewyp  
    OP
       2021-01-16 18:36:14 +08:00
    @tmackan inspect 刚才 我也简单看了下 貌似确实不满足
    dwadewyp
        14
    dwadewyp  
    OP
       2021-01-16 18:41:17 +08:00
    已解决:
    在 animal __init__.py
    ```
    import os
    import pkgutil

    pkgpath = os.path.dirname(__file__)
    pkgname = os.path.basename(pkgpath)

    for _, file, _ in pkgutil.iter_modules([pkgpath]):
    __import__(pkgname+'.'+file)
    ```
    julyclyde
        15
    julyclyde  
       2021-01-18 14:21:20 +08:00
    安装包的时候注册 entrypoint,然后 init 阶段遍历加载
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2405 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 02:00 · PVG 10:00 · LAX 18:00 · JFK 21:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.