2014-03-06 65 views
4

我想寫一個程序,它接受一個數字p作爲輸入,併產生一個數字的類型構造函數,該數字遵從整數運算模p。什麼是「元類」的方式來做到這一點?

到目前爲止,我有

def IntegersModP(p): 
    N = type('IntegersMod%d' % p,(), {}) 

    def __init__(self, x): self.val = x % p 
    def __add__(a, b): return N(a.val + b.val) 
    ... (more functions) ...  

    attrs = {'__init__': __init__, '__add__': __add__, ... } 

    for name, f in attrs.items(): 
     setattr(N, name, f) 

    return N 

這工作得很好,但我想知道什麼是Python的方式做,這是我的理解會用元類。

+0

爲什麼要使用元類? – user2357112

+0

我不知道你爲什麼想在這裏使用元類,你可以使用一個簡單的類語句並將'p'傳遞給'__init__'。 –

+0

@AshwiniChaudhary這是不可接受的,因爲你不應該能夠添加兩個不同模數的實例。 (您將使用哪種模數?) – JeremyKun

回答

1

元類是當你的類需要從正常類行爲不同,或當你想改變class語句的行爲。這些都不適用於此,因此實際上不需要使用元類。事實上,你可以只是與記錄他們的價值和模量的情況下,一個ModularInteger類,但假設你不想這樣做,它仍然很容易與普通類語句來做到這一點:

def integers_mod_p(p): 
    class IntegerModP(object): 
     def __init__(self, n): 
      self.n = n % IntegerModP.p 
     def typecheck(self, other): 
      try: 
       if self.p != other.p: 
        raise TypeError 
      except AttributeError: 
       raise TypeError 
     def __add__(self, other): 
      self.typecheck(other) 
      return IntegerModP(self.n + other.n) 
     def __sub__(self, other): 
      ... 
    IntegerModP.p = p 
    IntegerModP.__name__ = 'IntegerMod{}'.format(p) 
    return IntegerModP 
+0

@AshwiniChaudhary:確實。我會用更復雜的'typecheck'來處理它,但我分心並忘記了。 – user2357112

+0

我認爲我對此沒有完全滿意,因爲我希望儘可能避免錯誤(並且最終我計劃讓這個類更加通用,所以我想在可能的情況下進行一些靜默類型轉換)。但我認爲你已經告訴我,我只需要更加努力地思考如何組織事情,這對於我所說的問題來說是一個很好的答案。 – JeremyKun

2

像這樣:

def IntegerModP(p): # class factory function 
    class IntegerModP(object): 
     def __init__(self, x): 
      self.val = x % p 
     def __add__(a, b): 
      return IntegerModP(a.val + b.val) 
     def __str__(self): 
      return str(self.val) 
     def __repr__(self): 
      return '{}({})'.format(self.__class__.__name__, self.val) 

    IntegerModP.__name__ = 'IntegerMod%s' % p # rename created class 
    return IntegerModP 

IntegerMod4 = IntegerModP(4) 
i = IntegerMod4(3) 
j = IntegerMod4(2) 
print i + j  # 1 
print repr(i + j) # IntegerMod4(1) 
+0

您可能希望在類上存儲'p'而不是將其作爲閉包變量,以便於內省,並添加一些類型檢查,以便在不同moduluses中使用數字進行數學運算不會給出錯誤的結果。 – user2357112

+1

@ user2357112:我只是勾畫出一種「Pythonic」的方式來爲OP構建這樣一個類,而不是實現僅僅在問題中被模糊定義的東西 - 此外,類的最終名稱應該足夠用於反思目的。 – martineau

相關問題