简体   繁体   English

如何创建一个仅在满足某些条件时才进行实例化的类?

[英]How do I create a class where instantiation only happens if certain conditions are met?

Let's say I have this class:假设我有这门课:

class Person:
    def __init__(self, name):
        self.name = name

If I want to instantiate Person I can do:如果我想实例化Person我可以这样做:

me = Person("António")

But what if I only want to instantiate Person if name has type str ?但是如果我只想实例化Person如果name类型是str呢?
I tried this:我试过这个:

class Person:
    def __init__(self, name):
        if type(name) == str:
            self.name = name

But then when I do:但是当我这样做时:

me = Person("António")
print(me.name)

you = Person(1)
print(you.name)

I get this:我明白了:

在此处输入图片说明

So all that's happening is:所以发生的一切是:

  • If name is str , the instance has a .name method如果namestr ,则实例有一个.name方法
  • If name is not str , the instance has no .name method如果name不是str ,则实例没有.name方法

But what I actually want, is to stop instantiation all together if name is not an str .但我真正想要的是,如果 name 不是str ,则一起停止实例化。
In other words, I want it to be impossible to create an object from the Person class with a non str name .换句话说,我希望不可能从Person类创建一个非str name

How can I do that?我怎样才能做到这一点?

You could use a factory that checks the parameters, and returns a Person object if everything is fine, or raises an error:您可以使用工厂来检查参数,如果一切正常或引发错误,则返回一个Person对象:

maybe something line this:也许是这样的:

class PersonNameError(Exception):
    pass

class Person:
    def __init__(self):
        self.name = None

def person_from_name(name: str) -> Person:
    """Person factory that checks if the parameter name is valid
    returns a Person object if it is, or raises an error without 
    creating an instance of Person if not.
    """
    if isinstance(name, str):
        p = Person()
        p.name = name
        return p
    raise PersonNameError('a name must be a string')

p = person_from_name('Antonio') 

Whereas:然而:

p = person_from_name(123)   # <-- parameter name is not a string

throws an exception:抛出异常:

PersonNameError                           Traceback (most recent call last)
<ipython-input-41-a23e22774881> in <module>
     14 
     15 p = person_from_name('Antonio')
---> 16 p = person_from_name(123)

<ipython-input-41-a23e22774881> in person_from_name(name)
     11         p.name = name
     12         return p
---> 13     raise PersonNameError('a name must be a string')
     14 
     15 p = person_from_name('Antonio')

PersonNameError: a name must be a string

How about :怎么样 :

class Person:
    def __init__(self, name):
        if type(name) == str:
            self.name = name
        else: 
            raise Exception("name attribute should be a string")

You should use factory design pattern .您应该使用factory design pattern You can read more about it here .您可以在此处阅读更多相关信息。 To put it simple:简单来说:

Create Class/method that will check for the conditions and return new class instance only if those conditions are met.创建将检查条件并仅在满足这些条件时返回新类实例的类/方法。

If you want to modify instantiation behaviour, You can create a constructor, using a class method.如果要修改实例化行为,可以使用类方法创建构造函数。

class Person:
    def __init__(self, name):
        self.name = name
        print("ok")

    @classmethod
    def create(cls, name):
        if not isinstance(name, str):
            raise ValueError(f"Expected name to be a string, got {type(name)}")
        return cls(name)
           
me = Person.create("António")
print(me.name)

you = Person.create(1)
print(you.name)

OK prints once proving only once instantiation OK 打印一次,只证明一次实例化

ok
António
Traceback (most recent call last):
  File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 31, in <module>
    start(fakepyfile,mainpyfile)  File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 30, in start
    exec(open(mainpyfile).read(),  __main__.__dict__)
  File "<string>", line 17, in <module>
  File "<string>", line 11, in create
ValueError: Expected name to be a string, got <class 'int'>

[Program finished]

Here, it's an explicit test that's being done.在这里,这是一个正在完成的显式测试。 Overriding new is very rarely needed and for everyday normal classes I think it should be avoided.很少需要覆盖new并且对于日常正常课程,我认为应该避免它。 Doing so keeps the class implementation simple.这样做可以使类实现简单。

class Test(object):
     print("ok")
     def __new__(cls, x):
         if isinstance(x, str) :           
             print(x)
         else:
             raise ValueError(f"Expected name to be a string, got {type(x)}")
 
obj1 = Test("António")

obj2 = Test(1)
ok
António
Traceback (most recent call last):
  File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 31, in <module>
    start(fakepyfile,mainpyfile)  File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 30, in start
    exec(open(mainpyfile).read(),  __main__.__dict__)
  File "<string>", line 14, in <module>
  File "<string>", line 10, in __new__
ValueError: Expected name to be a string, got <class 'int'>

[Program finished]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如果满足某些条件,如何在继续下一次迭代之前保持在 for 循环中? - How do I stay within a for loop if certain conditions are met, before continuing to the next iteration? 在满足特定条件的情况下过滤 DataFrame 中的行? - Filter rows in DataFrame where certain conditions are met? 在满足特定条件的情况下,如何找到字典中某个值的平均值? - How do I find the average of a value in a dictionary, where a certain condition is met? 如何在Python Pandas数据帧列上执行数学运算,但仅限于满足某个条件? - How do I perform a math operation on a Python Pandas dataframe column, but only if a certain condition is met? 我如何定义一个类,在实例化时赋予它的参数变成其实例变量? - How do I define a class where the arguments given to it on instantiation becomes its instance variables? 如果满足某些条件,如何配置Tkinter小部件? - How to configure Tkinter widgets if certain conditions are met? 满足条件后如何让消息框出现? - How do I make the messagebox appear after the conditions are met? 如何创建“列表”类的子类,该子类在实例化时进行排序? - How do I create a Subclass of the “list” class, that sorts itself upon instantiation? django仅在满足某些条件时才将数据保存在数据库中 - django save data in database only when certain conditions are met 根据之前列中满足的某些条件,在 dataframe 中创建新列 - Create new column in dataframe based on certain conditions met in previous columns
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM