【问题标题】:python class adds instances of itself to a listpython类将自身的实例添加到列表中
【发布时间】:2013-10-10 12:02:30
【问题描述】:

我有一个房间类。我希望每次使用该类创建对象时,该对象都会添加到所有房间的列表中。 房间等级:

class Rooms:
    """Room class, takes type,days,  occupied or not and when it frees up"""
    def __init__(self, room_type, days, occupied, when_free):
        self.room_type = room_type
        self.days = days
        self.occupied = occupied
        self.when_free = arrow.get(when_free,'YYYY-MM-DD')

也欢迎任何其他反馈!

也不确定我是否应该为此创建新主题,但是否有可能在创建对象并将 True onoccuped 传递给对象时,您不需要传递第 4 个变量,它会将其作为当前变量约会呢?简而言之,如果没有第四个变量,它会通过 arrow.get(str(arrow.utcnow()),'YYYY-MM-DD')

解决了我的第二个问题。我确实将 init 更改为:

def __init__(self, room_type, days, occupied, when_free=str(arrow.get(str(arrow.utcnow()),'YYYY-MM-DD'))):
        self.room_type = room_type
        self.days = days
        self.occupied = occupied
        self.when_free = arrow.get(when_free,'YYYY-MM-DD')

【问题讨论】:

  • 你的第一个问题是什么?
  • 什么是箭头? “房间列表”在哪里?
  • arrow 是一个时间库(请参阅crsmithdev.com/arrow),我还没有真正的 list_of_rooms 任何地方,我想我应该在某个地方将它作为全局变量运行?
  • 在创建Room 时将Room 添加到列表中如何?我不认为 Room 应该将自己添加到全局变量中。
  • 是的,目前我只是在它下面的另一行中创建一个对象后将一个房间添加到列表中,但我认为也许会有更有效的方法。

标签: python class object initialization


【解决方案1】:

我会建议一种比the above 更优雅和合乎逻辑的方式:

class Building(object):
    def __init__(self):
        self.rooms = []

class Room(object):
    def __init__(self, building=None)

        if building:
            building.rooms.append(self)
        self.building = building

b = Building()
r = Room(b)

这样你就不需要每次都调用b.rooms.append,现在更符合OOP了。

【讨论】:

  • 是的,这正是我所要求的,但是上面发布的方法似乎已经足够了,但是仍然感谢您教我这个!
【解决方案2】:

理想情况下,您希望房间列表的范围是您计划使用它的地方。不是房间本身的一部分。所以,如果你有一栋带房间的建筑:

class Building():
    def __init__(self):
        self.rooms = []

b = Building()
b.rooms.append(Room(room_type, days, occupied, when_free))

该建筑只是一个例子。重要的部分是rooms.append()。应该在您实际需要使用房间列表的任何地方声明和使用它。

【讨论】:

  • 啊,这很有意义。谢谢
【解决方案3】:

将列表设为类变量可能会更好:

class Room(object):
    rooms = []
    def __init__(self, room_type, days, occupied, when_free):
        self.room_type = room_type
        self.days = days
        self.occupied = occupied
        self.when_free = arrow.get(when_free,'YYYY-MM-DD')
        Room.rooms.append(self)

r = Room('x', 1,2, True)
Room.rooms
[<Room object at 0x00000000C6325550>]
r.rooms
[<Room object at 0x00000000C6325550>]

由于它是一个类变量,您可以通过任何类实例或类类型本身来获取它。

编辑为通过“房间”而不是“自我”,这样更安全...

【讨论】:

  • 请注意,理想情况下,您还需要添加一些内容以在房间被破坏时从列表中删除它。
  • 一个类变量在每个对象中保留相同的值吗?
  • @Granitas,不,仅当对象本身未声明该名称时。不要这样做。显式使用Room.rooms.append(self)
  • 这是真的......所以,以上确实有效。当它获得一个名字时,它会先遍历实例变量,然后是类变量。 Room.rooms 将始终指向该列表;有人可以继承 Room 并创建自己的房间变量,self.rooms 将指向那个变量,而 Room.rooms 仍然指向类变量。
【解决方案4】:

我在想您可以使用将实例附加到列表的装饰器来装饰 __init__ 方法,以避免在实例注册时弄乱 __init__ 方法。现在,如果您想跟踪实例,您只需向每个类的 init 方法添加一个装饰器。比如:

#!/usr/bin/env python3

import sys

class InstanceRegister:
    def __call__(self, init):
        def register(instance, *args, **kwargs):
            init(instance, *args, **kwargs)
            try :
                instance.__class__.__instances__
            except:
                instance.__class__.__instances__ = []
            instance.__class__.__instances__.append(instance)
        return register

class Room:
    """Room class, takes type,days,  occupied or not and when it frees up"""
    @InstanceRegister()
    def __init__(self, room_type, days, occupied, when_free):
        self.room_type = room_type
        self.days = days
        self.occupied = occupied
        self.when_free = arrow.get(when_free,'YYYY-MM-DD')

    def __str__(self):
        return "Room of type {:s}".format(self.room_type)



def main():
    r1 = Room('type_a', 1, True, '1999-12-30')
    r2 = Room('type_b', 2, True, '2000-12-30')
    r3 = Room('type_c', 3, True, '2001-01-30')
    for room in Room.__instances__:
        print("{:s}".format(room))
    return 0

if __name__ == '__main__':
    sys.exit(main())

Understanding Python Decorators in 12 Easy Steps! 上有关装饰器的更多信息

【讨论】:

  • 这有点超出我的范围。
  • @KillianDS 第一次你想这样做是对的,也许第二次也是如此,但到第三次你就不想再写相同的代码了!
  • @KillianDS 所以你更喜欢写 200000 行而不是数量少得多的 100010 行?我觉得这很奇怪。
猜你喜欢
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-19
  • 1970-01-01
  • 1970-01-01
  • 2011-10-11
  • 1970-01-01
相关资源
最近更新 更多