2015-11-19 63 views
3

考慮以下問題最小:方法對象從類轉換爲子類在Python

from math import sqrt  

class Vector(object): 

    def __init__(self, x, y, z): 
     self.v = [x, y, z] 

    def normalize(self): 
     x, y, z = self.v 
     norm = sqrt(x**2 + y**2 + z**2) 
     self.v = [x/norm, y/norm, z/norm] 

    # other methods follow 

class NormalizedVector(Vector): 

    def __init__(self, x, y, z): 
     super(Vector, self).__init__(x, y, z) 
     self.normalize() 

所以基本上NormalizedVector對象是一樣的矢量對象,但與添加的正常化。

是否有可能向Vector添加一個方法,以便每當調用normalize方法時,該對象會自動分類到NormalizedVector?

我知道我可以使用abstract factory pattern,但這隻有在創建時創建子對象時纔有效:我希望能夠繼承先前已創建的對象。

我發現some solutions基於重新分配__類__方法,但不鼓勵這些方法。我願意修改上面的模式,使其更加「Pythonic」。

+3

中找到可能的操作列表爲什麼不只使用具有布爾型「規範化」實例屬性的Vector類? –

+0

我會做的,謝謝! –

回答

2

我建議僅使用Vector()類和布爾型normalized實例屬性。

此外,在normalize方法使用的是Xÿž,但這些變量沒有定義,你甚至不與self閱讀它們。

的代碼,我會建議:

from math import sqrt  

class Vector(object): 

    def __init__(self, x, y, z, normalized=False): 
     self.v = [x, y, z] 
     if normalized in [True, False]: 
      self.normalized = normalized 
     else: 
      raise Exception("Please set normalized to either True or False") 

    def __repr__(self): 
     return "Vector ({}, {}, {})".format(*self.v) 

    def normalize(self): 
     x,y,z = self.v 
     norm = sqrt(x**2 + y**2 + z**2) 
     self.v = [x/norm, y/norm, z/norm] 
     self.normalized = True 

    def isNormalized(self): 
     return self.normalized 

    # other methods follow 

v1 = Vector(10, 20, 30) 
print v1.isNormalized() 
v1.normalize() 
print v1.isNormalized() 

v2 = Vector(40, 50, 60, normalized=True) 
print v2.isNormalized() 

輸出:

False 
True 
True 


__repr__功能將只顯示出良好的再你的對象的呈現:

print v1 

輸出:

Vector (0.267261241912, 0.534522483825, 0.801783725737) 
+0

一個向量可以被初始化爲規範化的'(1,0,0)',但是如果這個重要或不重要的話,它的某些東西可以由代碼的用戶來決定。此外,如果有任何操作正在改變實例,則需要重置此屬性。 – Caramiriel

+0

@Caramiriel,然後只是(因爲我已經更新)設置一個'normalized' kwarg與'default = False',如果他想將de Vector初始化爲一個'normalized',他可以在構造函數中指定它。 –

1

爲什麼你需要跟蹤的載體本身正常化,只是跟蹤它在你的main.py或任何你」重新使用矢量?

此外,我只是簡單地返回一個標準值的對象的新副本。這樣,您可以在計算中快速創建標準化矢量,而無需更改原始矢量。

from math import sqrt  

class Vector(object): 

    def __init__(self, x, y, z): 
     self.v = [x, y, z] 

    def normalized(self): 
     x, y, z = self.v 
     norm = sqrt(x**2 + y**2 + z**2) 
     return Vector(x/norm, y/norm, z/norm) 

如果您有需要正常化真正許多載體,可以歸他們分成兩個列表或元組,或者你想有一個名單什麼的,這裏有一個字典例如:

vectors = {} 
for x, y, z in zip(range(10), range(10), range(10)): 
    v = Vector(x, y, z) 
    vectors[v] = v.normalize() 

如果你只是有幾個向量或隨機需要爲某個計算規則化一個向量,您可以隨時手動跟蹤它們或在計算中動態創建它們,而無需更改原始向量:v_norm = v.normalized()

0

如果你真的想保留這兩個類,你可以覆蓋這些類的操作。

假設你想添加矢量和歸一化的矢量。你可以不喜歡這樣

從數學進口開方

class Vector: 

    def __init__(self,x,y): 
     self.x = x 
     self.y = y 

    def __add__(self,v): 
     if isinstance(v,Vector): 
      return (self.x+v.x,self.y+v.y) 
     elif isinstance(v,NormVector): 
      n = NormVector(self.x,self.y) 
      return (n.x+v.x,n.y+v.y) 

class NormVector: 

    def __init__(self,x,y): 
     self.x = x/sqrt(x**2 + y**2) 
     self.y = y/sqrt(x**2 + y**2) 

    def __add__(self,v): 
     if isinstance(v,Vector): 
      n = NormVector(v); 
      return (self.x + n.x,self.y + n.y) 
     elif isinstance(v,NormVector): 
      return (self.x+v.x,self.y+v.y) 


a = Vector(5,0) 
b = NormVector(0,3) 
c = a + b 
print c 

這樣你就可以覆蓋你需要的任何功能。可以在documentation

相關問題