[英]python 3: how do I create two different classes that operate on the same data?
我有一堂課,看起來像下面這樣:
# Class violates the Single Responsibility Principle
class Baz:
data = [42]
def do_foo_to_data(self):
# call a dozen functions that do complicated stuff to data
def do_bar_to_data(self):
# call other functions that do different stuff to data
我想將其分為兩個單獨的類,因為它違反了SRP。 通過調用的函數do_foo_to_data()
是從那些通過調用完全不同do_bar_to_data()
但是它們必須對相同的data
。
我已經提出了很多解決方案,但是它們都很難看。 有沒有一種方法可以干凈地做到這一點,最好是在Python 3中(盡管2.7也可以)?
我最好的“解決方案”如下:
# I find this hard to read and understand
class Baz:
data = [42]
def create_foo(self):
return Baz.Foo()
def create_bar(self):
return Baz.Bar()
class Foo:
def do_foo_to_data(self):
# call foo functions
class Bar:
def do_bar_to_data(self):
# call bar functions
注意: data
成員成為類成員對我來說不是必需的。 我只期望創建一個Baz
實例; 但是我不想在一個帖子中問兩個問題,而是開始討論單身人士。
這不是一個很好的解決方案。 您最好將引用傳遞給您要對其進行操作的對象。 所以像這樣:
class Foo:
def __init__(self,data): self.data = data
def do_foo_to_data(self):
#...
self.data[0] = 14
pass
class Bar:
def __init__(self,data): self.data = data
def do_bar_to_data(self):
#...
self.data.append(15)
pass
(我添加了示例操作,例如self.data[0] = 14
和self.data.append(15)
)
現在,您可以構建數據了。 例如:
data = [42]
接下來,構造Foo
和Bar
並傳遞對data
的引用,例如:
foo = Foo(data)
bar = Bar(data)
__init__
是大多數編程語言稱為構造函數的結構 ,正如您在第一個片段中所看到的那樣,它需要附加的參數data
(在這種情況下,它是對我們構造的data
的引用)。
然后您可以例如致電:
foo.do_foo_to_data()
它將data
設置為[14]
然后
bar.do_bar_to_data()
這將導致data
等於[14,15]
。
請注意,您無法聲明 self.data = ['a','new','list']
或do_foo_to_data
或do_bar_to_data
等效項,因為這會更改對新對象的引用 。 相反,您可以例如.clear()
列表,並向其添加新元素,例如:
def do_foo_to_data(self): #alternative version
#...
self.data.clear()
self.data.append('a')
self.data.append('new')
self.data.append('list')
最后回答您的評論:
最好在Python 3中使用(盡管2.7也可以)?
演示的技術幾乎是通用的(意味着幾乎每種編程語言都可以使用)。 因此,這將適用於python-3.x和python-2.7 。
為什么你甚至需要一堂課? 您只需要兩個獨立的函數,即可對某些數據進行某些處理。
data = [42]
def foo(data):
data.append('sample operation foo')
def bar(data):
data.append('sample operation bar')
問題解決了。
您可以提取不同的功能組來分離混合類:
class Foo:
"""Mixin class.
Requires self.data (must be provided by classes extending this class).
"""
def do_foo_to_data(self):
# call a dozen functions that do complicated stuff to data
class Bar:
"""Mixin class.
Requires self.data (must be provided by classes extending this class).
"""
def do_bar_to_data(self):
# call other functions that do different stuff to data
class Baz(Foo, Baz):
data = [42]
這依賴於Python的鴨式行為。 您應該僅將Foo
和Bar
混合應用到實際提供self.data
的類,就像這里的Baz
類一樣。
按照慣例,某些類需要提供某些屬性,這可能是合適的,例如Django中的自定義視圖類。 但是,如果尚未建立這樣的約定,則可能不希望引入新的約定。 錯過文檔,然后在運行時出現NameError
太容易了。 因此,讓我們明確顯示依賴項,而不是僅對其進行記錄。 怎么樣? 帶有用於混入的混入!
class Data:
"""Mixin class"""
data = [42]
class Foo(Data):
"""Mixin class"""
def do_foo_to_data(self):
# call a dozen functions that do complicated stuff to data
class Bar(Data):
"""Mixin class"""
def do_bar_to_data(self):
# call other functions that do different stuff to data
class Baz(Foo, Baz):
pass
在這個抽象級別上很難說這是否適合您的用例。 正如RayLuo的答案所示,您可能根本不需要類。 相反,您可以將不同的功能組放入不同的模塊或包中,以進行組織。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.