我需要帮助创建一个对象(一个数字序列)关于一个类的一些参数。假设我输入了Python空闲shell:
SuperLotto = make_lottery_set_type('SuperLotto', 6, (1,50))
#means user can create a 'SuperLotto' with 6 numbers in range of 1 to 50
它将使“超级乐透”成为名为“LotteryGameType”的类的新类实例。你知道吗
到目前为止,这是在使用代码:
class LotterySetError(Exception):
pass
def make_lottery_set_type(name:str, size:int, minmax:tuple):
if minmax[0] > minmax[1]:
raise LotterySetError('Illegal range for tuple')
else:
name = LotteryGameType(name, size, minmax[0], minmax[1])
return name
class LotteryGameType:
def __init__(self, name, set_size, min_set_number, max_set_number):
self.name = name
self.set_size = set_size
self.min_set_number = min_set_number
self.max_set_number = max_set_number
我希望能够创建一个数字序列并将其存储起来以备以后使用,这样我就可以将其与重载运算符(例如eq和ne)一起使用。你知道吗
我希望能够在Python空闲shell中键入:
SuperLotto([3, 4, 19, 23, 46, 27])
这将在SuperLotto的参数下创建一个对象,如果不是在“SuperLotto”的参数下(比如超过6个数字),则会产生错误。任何方法都可以。有人对如何处理这个问题有什么想法吗?你知道吗
听起来您想要的是
make_lottery_set_type
返回一个新的class
,可能是LotteryGameType
的子类,而不是返回该类型的实例。你知道吗在Python中,这实际上很容易做到。类定义只是普通的代码,可以在任何地方运行,甚至在函数的中间。它们在运行时可以访问本地环境。类本身是“第一类值”,这意味着您可以传递它们并从函数返回它们。所以:
如果要添加其他方法,这与向任何其他类添加方法相同。例如:
所以:
(显然,如果set equality不是适合您使用的规则,您可以根据需要定义
__eq__
)如果您尝试检查生成的值,它们看起来并不像您希望的那么漂亮。例如,您可能更愿意在这样的地方看到
SuperLotto
而不是NewLotteryGameType
:为此,只需添加
NewLotteryGameType.__name__ = name
。您可能还想从父类复制docstring或其他各种内容。你知道吗一般来说,请看
functools.update_wrapper
(它是为包装函数而设计的,而不是类,但许多细节是相同的)以获得灵感,并查看Python版本中的inspect
模块文档以了解类可以拥有的所有属性。你知道吗在评论中,你会问:
这是自相矛盾的。如果您想继承
LotteryGameType
的实例属性,那么您已经继承了。例如:如果您想让它们在类外可以访问,那么它们不能是实例属性,必须是类属性。仅仅将
set_size
更改为LotteryGameType
的class属性并继承它是行不通的,因为class属性的关键是类的所有实例或其任何子类共享相同的值,子类都需要不同的值。你知道吗但你可以这样做:
(注意,由于作用域的工作方式,我不得不将第一个
make_
参数重命名为lottery_name
,因此它与类属性name
不同。)现在,name
和set_size
不是实例属性,也不是LotteryGameType
的类属性,而是每个NewLotteryGameType
的类属性。所以:如果创建这些类型的实例呢?嗯,Python在实例中查找属性,然后在最派生的类中查找属性,然后在基类中查找属性。因此,只要您不使用相同的名称创建实例属性(请注意,我从
LotteryGameType.__init__
方法中删除了额外的参数和设置实例属性的代码),它就会执行您想要的操作:当然,这意味着
LotteryGameType
本身不再是可用的类型;只有它的子类才是可用的。但这可能正是你想要的,对吧?您甚至可以考虑显式地将其设置为abstract base class,以确保没有人意外地尝试使用直接LotteryGameType
实例。你知道吗如果你觉得很勇敢,你可能想读一下元类,看看如何将整个设计改编成一个} 模块的源代码,或者近似等效的外部^{} 包,可能是很好的示例代码。然后你可以把两者都玩一玩,看看它们有多相似,有多不同。你知道吗
LotteryGameMetaclass
,因此每个新类都是元类的一个实例,而不是(抽象)基类的一个子类。3.4中新的^{相关问题 更多 >
编程相关推荐