python 3:如何创建两个对相同数据进行操作的不同类?
python 3: how do I create two different classes that operate on the same data?
我有一个 class 看起来像下面这样:
# 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
我想将其分成两个单独的 classes,因为它违反了 SRP。 do_foo_to_data()
调用的函数与do_bar_to_data()
调用的函数完全不同。然而它们必须在相同的 data
.
上运行
我想出了一堆解决方案,但它们都很丑陋。有没有办法干净地做到这一点,最好是 Python 3(尽管 2.7 也可以)?
我的"solutions"最好的如下:
# 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
成员必须是 class 成员。
我只希望创建一个 Baz
的实例;但我不想一口气问两个问题 post 然后开始讨论单身人士。
这不是一个优雅的解决方案。您最好将引用 传递给您希望它们操作的对象。所以像:
class Foo:
<b>def __init__(self,data):
self.data = data</b>
def do_foo_to_data(self):
#...
self.data[0] = 14
pass
class Bar:
<b>def __init__(self,data):
self.data = data</b>
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')
终于回答你的问题了:
preferably in Python 3 (though 2.7 is OK too)?
展示的技术几乎是通用的(这意味着它在几乎每种编程语言中都可用)。所以这将适用于 python-3.x and python-2.7.
为什么你甚至需要 class?你想要的只是两个独立的函数,它们对一些数据做一些工作。
data = [42]
def foo(data):
data.append('sample operation foo')
def bar(data):
data.append('sample operation bar')
问题已解决。
您可以提取不同的功能组来分隔 mix-in classes:
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 的 duck-typing 行为。您应该只将 Foo
和 Bar
mix-in 应用于实际提供 self.data
的 class,例如 Baz
class这里有。
这可能适用于某些 classes 按惯例无论如何都需要提供某些属性的情况,例如 Django 中的自定义视图 classes。但是,当此类约定尚未到位时,您可能不想引入新约定。错过文档然后在运行时有 NameError
s 太容易了。因此,让我们明确说明依赖关系,而不仅仅是记录它。如何?用 mix-in 表示 mix-ins!
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
这是否适合您的 use-case 在这个抽象层次上很难说。正如 所示,您可能根本不需要 classes。相反,您可以将不同的功能组放入不同的模块或包中,以组织它们。
我有一个 class 看起来像下面这样:
# 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
我想将其分成两个单独的 classes,因为它违反了 SRP。 do_foo_to_data()
调用的函数与do_bar_to_data()
调用的函数完全不同。然而它们必须在相同的 data
.
我想出了一堆解决方案,但它们都很丑陋。有没有办法干净地做到这一点,最好是 Python 3(尽管 2.7 也可以)?
我的"solutions"最好的如下:
# 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
成员必须是 class 成员。
我只希望创建一个 Baz
的实例;但我不想一口气问两个问题 post 然后开始讨论单身人士。
这不是一个优雅的解决方案。您最好将引用 传递给您希望它们操作的对象。所以像:
class Foo:
<b>def __init__(self,data):
self.data = data</b>
def do_foo_to_data(self):
#...
self.data[0] = 14
pass
class Bar:
<b>def __init__(self,data):
self.data = data</b>
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')
终于回答你的问题了:
preferably in Python 3 (though 2.7 is OK too)?
展示的技术几乎是通用的(这意味着它在几乎每种编程语言中都可用)。所以这将适用于 python-3.x and python-2.7.
为什么你甚至需要 class?你想要的只是两个独立的函数,它们对一些数据做一些工作。
data = [42]
def foo(data):
data.append('sample operation foo')
def bar(data):
data.append('sample operation bar')
问题已解决。
您可以提取不同的功能组来分隔 mix-in classes:
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 的 duck-typing 行为。您应该只将 Foo
和 Bar
mix-in 应用于实际提供 self.data
的 class,例如 Baz
class这里有。
这可能适用于某些 classes 按惯例无论如何都需要提供某些属性的情况,例如 Django 中的自定义视图 classes。但是,当此类约定尚未到位时,您可能不想引入新约定。错过文档然后在运行时有 NameError
s 太容易了。因此,让我们明确说明依赖关系,而不仅仅是记录它。如何?用 mix-in 表示 mix-ins!
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
这是否适合您的 use-case 在这个抽象层次上很难说。正如