2010-09-01 30 views
0

我有一個知道它的現有實例的類。有時我想讓類構造函數返回一個現有的對象,而不是創建一個新的對象。python:獲取構造函數返回一個現有的對象,而不是一個新的

class X: 
    def __new__(cls, arg): 
     i = f(arg) 
     if i: 
      return X._registry[i] 
     else: 
      return object.__new__(cls) 
    # more stuff here (such as __init_, _registry, etc.) 

當然,如果執行的第一個分支,我不需要__init__,但它反正調用。告訴__init__什麼都不做的好方法是什麼?

我可能只是添加一些屬性來跟蹤__init__是否已經運行,但也許有更好的方法?

+0

您不需要構造函數。你需要一個工廠方法。正是因爲這個原因,爲什麼許多爭論的建設者應該是私人的,你應該(幾乎)總是通過工廠方法。 – cletus 2010-09-01 06:40:53

回答

1

使用一個工廠,即

_x_singleton = None 

def XFactory(): 
    global _x_singleton 

    if _x_singleton is None: 
     _x_singleton = X() 
    return _x_singleton 

,或者使用「創建」,在你的類類方法的行爲方式,你希望它的方式,

class X(object): 
    instance = None 
    def __init__(self): 
     # ... 
    @classmethod 
    def create(cls): 
     if cls.instance is None: 
      cls.instance = cls() 
     return cls.instance 

你甚至可以考慮讓__init__引發例外,如果某些條件不滿足(即self.instance不是無)

1

在支持私有構造函數(C#,Dart,Scala等)的語言中,工廠方法ds爲這個問題提供了強大的解決方案。

然而,在Python中,類的構造函數總是可以訪問的,所以你的類的用戶可能很容易忘記工廠方法並直接調用構造函數,產生應該是唯一的對象的重複副本。

使用元類可以實現這個問題的一個傻瓜式解決方案。下面的示例假定零構造函數的參數可以用來唯一標識每個實例:

class Unique(type): 

    def __call__(cls, *args, **kwargs): 
     if args[0] not in cls._cache: 
      self = cls.__new__(cls, *args, **kwargs) 
      cls.__init__(self, *args, **kwargs) 
      cls._cache[args[0]] = self 
     return cls._cache[args[0]] 

    def __init__(cls, name, bases, attributes): 
     super().__init__(name, bases, attributes) 
     cls._cache = {} 

可以使用如下:

class Country(metaclass=Unique): 
    def __init__(self, name: str, population: float, nationalDish: str): 
     self.name = name 
     self.population = population 
     self.nationalDish = nationalDish 

placeA = Country("Netherlands", 16.8e6, "Stamppot") 
placeB = Country("Yemen", 24.41e6, "Saltah") 
placeC = Country("Netherlands", 11, "Children's tears") 

print(placeA is placeB) # -> False 
print(placeA is placeC) # -> True 
print(placeC.nationalDish) # -> Stamppot 

總之,如果你想這種做法是非常有用的在運行時產生一組獨特的對象(可能使用其中可能重複條目的數據)。

相關問題