簡體   English   中英

python 3:如何創建對相同數據進行操作的兩個不同的類?

[英]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] = 14self.data.append(15)

現在,您可以構建數據了。 例如:

data = [42]

接下來,構造FooBar傳遞對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_datado_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也可以)?

演示的技術幾乎是通用的(意味着幾乎每種編程語言都可以使用)。 因此,這將適用於

為什么你甚至需要一堂課? 您只需要兩個獨立的函數,即可對某些數據進行某些處理。

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的鴨式行為。 您應該僅將FooBar混合應用到實際提供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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM