模仿Python';s型

模仿Python';s型,python,metaclass,nonetype,Python,Metaclass,Nonetype,我正在创建几个类,将它们用作状态标志(这更像是一个练习,尽管我将在实际项目中使用它们),就像我们在Python中使用None,即 ... some_var is None ... NoneType有几个特殊属性,最重要的是它是一个单例,即在任何解释器会话期间不能有多个NoneType实例,其实例(None对象)是不可变的。我提出了两种可能的方法来在纯Python中实现一些类似的行为,我很想知道哪一种从体系结构的角度看更好 1.根本不要使用实例。 这个想法是要有一个元类,它生成不可变的类。这些类

我正在创建几个类,将它们用作状态标志(这更像是一个练习,尽管我将在实际项目中使用它们),就像我们在Python中使用
None
,即

... some_var is None ...
NoneType
有几个特殊属性,最重要的是它是一个单例,即在任何解释器会话期间不能有多个
NoneType
实例,其实例(
None
对象)是不可变的。我提出了两种可能的方法来在纯Python中实现一些类似的行为,我很想知道哪一种从体系结构的角度看更好

1.根本不要使用实例。 这个想法是要有一个元类,它生成不可变的类。这些类禁止有实例

class FlagMetaClass(type):
    def __setattr__(self, *args, **kwargs):
        raise TypeError("{} class is immutable".format(self))

    def __delattr__(self, *args, **kwargs):
        self.__setattr__()

    def __repr__(self):
        return self.__name__


class BaseFlag(object):
    __metaclass__ = FlagMetaClass

    def __init__(self):
        raise TypeError("Can't create {} instances".format(type(self)))

    def __repr__(self):
        return str(type(self))


class SomeFlag(BaseFlag):
    pass
我们得到了想要的行为

a = BaseFlag
a is BaseFlag  # -> True
a is SomeFlag  # -> False
显然,在这些类上设置属性的任何尝试都将失败(当然,有几种方法可以克服这一点,但直接的方法是封闭的)。类本身是加载在命名空间中的唯一对象

2.一个合适的单身阶级 这里的
标志
类是真正的单例。当我们尝试创建另一个实例时,这个特定的实现不会引发错误,但会返回相同的对象(尽管很容易改变这种行为)。类和实例都不能直接修改。关键是在导入时创建每个类的实例,就像使用
None
一样


这两种方法都给了我一些不可变的独特对象,它们可以用于比较,就像
None
一样。在我看来,第二个更像
NoneType
,因为
None
是一个实例,但我不确定它是否值得增加思想复杂性。期待您的来信。

理论上,这是一个有趣的练习。但当你说“虽然我将在一个真正的项目中使用它们”时,你就失去了我

如果真正的项目是高度不和谐的(使用traits或其他软件包来模拟静态类型,使用
\uuuuuu slots\uuuuuu
来防止人们落在尖锐的物体上,等等)——好吧,我没有任何东西给你,因为我没有用,但其他人有

如果真正的项目是Pythonic,那么尽可能做最简单的事情

您的“根本不使用实例”答案在这里是正确的,但是您也不需要做很多类定义

例如,如果您有一个函数可以接受None作为实参数,并且您想知道该参数是否已默认,那么只需执行以下操作:

class NoParameterGiven:
    pass

def my_function(my_parameter=NoParameterGiven):
    if my_parameter is NoParameterGiven:
        <do all my default stuff>

你不需要实例化任何东西,你可以这样引用它们:
MyStates.State1

如果你只是在寻找状态标志,那么为什么要尝试:(我认为你使用的是python 2.x)。@Dunes一个很好的链接,谢谢。另一个“命名单例”的可能性在sqlalchemy的
symbol
类中演示:这可能值得一看……最好使用一个类,因为如果您的标志之一是deepcopy,您将失去类似于singleton的引用,而如果输入是一个类,那么deepcopy将输出相同的引用。谢谢您的意见。我会等一会儿再接受它,以防有人想出另一个。
class NoParameterGiven:
    pass

def my_function(my_parameter=NoParameterGiven):
    if my_parameter is NoParameterGiven:
        <do all my default stuff>
class MyStates:
    class State1: pass
    class State2: pass
    class State3  pass