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
junezk
V2EX  ›  Python

如何在类定义中创建一个指向自身类型的属性?

  •  
  •   junezk · 2018-08-16 21:00:00 +08:00 · 1736 次点击
    这是一个创建于 2073 天前的主题,其中的信息可能已经有所发展或是发生改变。
    例如:
    class People(object):
    name = ""
    friend = People()

    由于 friend 还在类 People 的定义中,这里是不能引用 People 类的,请问这种情况代码该如何写?

    相似的还有:
    class A:
    b = B()

    class B:
    a = A()

    B 类可以引用 A 类,A 里面是不能引用 B 的,这种情况代码如何写?
    11 条回复    2018-08-16 23:02:21 +08:00
    j0hnj
        1
    j0hnj  
       2018-08-16 21:05:38 +08:00 via iPhone
    标准库里一般有两种做法,一种是像 enum 这样的用 metaclass 黑魔法,另一种就是先创建类,然后再添加属性,比如
    class A: pass
    class B: pass
    A.b = B()
    B.a = A()
    drlalll
        2
    drlalll  
       2018-08-16 21:05:55 +08:00
    应该用 new 新建对象吧
    junezk
        3
    junezk  
    OP
       2018-08-16 21:43:24 +08:00
    @j0hnj 其实出现这个需求是我在使用 django RESTframework 做序列化时遇到的。
    我在 django 中定义了一个类型的 model:

    class Channel(models.Model):
    """
    分类
    """
    name = models.CharField(verbose_name="分类名称", max_length=40)
    display_name = models.CharField(verbose_name="显示名称", max_length=40)
    parent = models.ForeignKey("Channel", null=True, blank=True, related_name="sub_channels", on_delete=models.SET_NULL)


    Channel 对象的 parent 属性可以指向自己类型的对象。

    做序列化时,就要定义
    class ChannelSerializer(serializers.ModelSerializer):
    parent = ChannelSerializer(read_only=True)

    class Meta:
    model = Channel
    fields = '__all__'
    这样的代码,这就不符合 Python 的语法了。
    使用你给出的解决办法,结果不对,没有达到享耀的效果。
    lynskylate
        4
    lynskylate  
       2018-08-16 21:46:50 +08:00 via Android
    classmethod 会传入这个 class
    junezk
        5
    junezk  
    OP
       2018-08-16 21:48:28 +08:00
    @lynskylate 请问 classmethod 该如何使用?查了些资料,都没提到解决这种情况的。
    junezk
        7
    junezk  
    OP
       2018-08-16 22:35:13 +08:00
    @vainl1 这和我问的问题有关系吗?
    Yourshell
        8
    Yourshell  
       2018-08-16 22:45:34 +08:00 via iPhone
    self.__class__
    lynskylate
        9
    lynskylate  
       2018-08-16 22:46:15 +08:00 via Android
    sorry 刚才没看仔细,其实一楼是符合你最初的描述的,不过不符合你的需求。
    你的要求是自引用序列化,可以看下这个,对于实在需要自定义程度很大的字段其实可以覆写他的 create valid 方法。
    http://www.google.com/url?q=https://stackoverflow.com/questions/13376894/django-rest-framework-nested-self-referential-objects&sa=U&ved=2ahUKEwihxJmZ5_HcAhXov1QKHT0ECmcQFjAAegQIBxAB&usg=AOvVaw06lQugVRb1STGxI0PRr3Lz
    junezk
        10
    junezk  
    OP
       2018-08-16 22:52:22 +08:00
    @Yourshell self 是在类的实例中使用的,引用类的实例,也就是对象本身。现在需要的是类定义时,引用其自身。或者两个类相互引用时,前一个类如何引用后一个类的类型。
    junezk
        11
    junezk  
    OP
       2018-08-16 23:02:21 +08:00
    @lynskylate 感谢,我需要的就是这个解决方案。baidu 搜了半天了也没找到相关的内容。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1514 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 17:04 · PVG 01:04 · LAX 10:04 · JFK 13:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.