接口隔离原则可以应用于 Python 对象吗?
Can Interface Segregation Principle be applied to Python objects?
努力应用 SOLID principles to a Python project that has grown organically and is in need of re-factoring, I am trying to understand how the Interface Segregation Principle 可以应用于 Python 语言,当接口不存在时语言功能?
接口是您可以键入提示的东西,字面上是在源代码中,或者只是非正式地在文档中。 Python 3 支持 function annotations, 3.5+ actual type hints,即使没有这些,您仍然可以在文档中简单地输入提示。类型提示只是表示特定参数应具有特定特征。
更具体地说:
interface Foo {
string public function bar();
}
function baz(Foo obj) { .. }
所有这些所做的就是声明传递给 baz
的任何参数都应该是一个对象,该对象的方法 bar
不带任何参数,returns 是一个字符串。即使 Python 没有在语言级别实施任何东西来 强制执行 ,您仍然可以通过多种方式声明这些东西。
Python 确实支持两个重要的事情:abstract classes 和多重继承。
而不是 interface Foo
,在 Python 你这样做:
import abc
class Foo(abc.ABC):
@abc.abstractmethod
def bar() -> str:
pass
而不是 implements Foo
,你这样做:
class MyClass(Foo):
def bar() -> str:
return 'string'
而不是 function baz(Foo obj)
,你这样做:
def baz(obj: Foo):
obj.bar()
由于多重继承特性,您可以根据需要将您的 interfaces/abstract 类 精细地分离。
Python 基于 duck-typing 原则,因此不是通过接口声明和继承强制执行所有这些,它通常根据 "parameter must be an iterable" 等更松散地定义,调用者只需要确保参数是 iterable。摘要 类 和函数注释,再加上正确的开发工具,可以帮助开发人员在不同的执行级别上遵守此类合同。
保持接口小并达到减少耦合的程度。耦合是指两个软件的连接有多紧密。接口定义的越多,实现 class 也需要做的越多。这使得 class 可重用性降低 .
我们来看一个简单的例子:
from abc import abstractmethod
class Machine:
def print(self, document):
raise NotImplementedError()
def fax(self, document):
raise NotImplementedError()
def scan(self, document):
raise NotImplementedError()
# ok if you need a multifunction device
class MultiFunctionPrinter(Machine):
def print(self, document):
pass
def fax(self, document):
pass
def scan(self, document):
pass
class OldFashionedPrinter(Machine):
def print(self, document):
# ok - print stuff
pass
def fax(self, document):
pass # do-nothing
def scan(self, document):
"""Not supported!"""
raise NotImplementedError('Printer cannot scan!')
class Printer:
@abstractmethod
def print(self, document): pass
class Scanner:
@abstractmethod
def scan(self, document): pass
# same for Fax, etc.
class MyPrinter(Printer):
def print(self, document):
print(document)
class Photocopier(Printer, Scanner):
def print(self, document):
print(document)
def scan(self, document):
pass # something meaningful
class MultiFunctionDevice(Printer, Scanner): # , Fax, etc
@abstractmethod
def print(self, document):
pass
@abstractmethod
def scan(self, document):
pass
class MultiFunctionMachine(MultiFunctionDevice):
def __init__(self, printer, scanner):
self.printer = printer
self.scanner = scanner
def print(self, document):
self.printer.print(document)
def scan(self, document):
self.scanner.scan(document)
printer = OldFashionedPrinter()
printer.fax(123) # nothing happens
printer.scan(123) # oops!
努力应用 SOLID principles to a Python project that has grown organically and is in need of re-factoring, I am trying to understand how the Interface Segregation Principle 可以应用于 Python 语言,当接口不存在时语言功能?
接口是您可以键入提示的东西,字面上是在源代码中,或者只是非正式地在文档中。 Python 3 支持 function annotations, 3.5+ actual type hints,即使没有这些,您仍然可以在文档中简单地输入提示。类型提示只是表示特定参数应具有特定特征。
更具体地说:
interface Foo {
string public function bar();
}
function baz(Foo obj) { .. }
所有这些所做的就是声明传递给 baz
的任何参数都应该是一个对象,该对象的方法 bar
不带任何参数,returns 是一个字符串。即使 Python 没有在语言级别实施任何东西来 强制执行 ,您仍然可以通过多种方式声明这些东西。
Python 确实支持两个重要的事情:abstract classes 和多重继承。
而不是 interface Foo
,在 Python 你这样做:
import abc
class Foo(abc.ABC):
@abc.abstractmethod
def bar() -> str:
pass
而不是 implements Foo
,你这样做:
class MyClass(Foo):
def bar() -> str:
return 'string'
而不是 function baz(Foo obj)
,你这样做:
def baz(obj: Foo):
obj.bar()
由于多重继承特性,您可以根据需要将您的 interfaces/abstract 类 精细地分离。
Python 基于 duck-typing 原则,因此不是通过接口声明和继承强制执行所有这些,它通常根据 "parameter must be an iterable" 等更松散地定义,调用者只需要确保参数是 iterable。摘要 类 和函数注释,再加上正确的开发工具,可以帮助开发人员在不同的执行级别上遵守此类合同。
保持接口小并达到减少耦合的程度。耦合是指两个软件的连接有多紧密。接口定义的越多,实现 class 也需要做的越多。这使得 class 可重用性降低 .
我们来看一个简单的例子:
from abc import abstractmethod
class Machine:
def print(self, document):
raise NotImplementedError()
def fax(self, document):
raise NotImplementedError()
def scan(self, document):
raise NotImplementedError()
# ok if you need a multifunction device
class MultiFunctionPrinter(Machine):
def print(self, document):
pass
def fax(self, document):
pass
def scan(self, document):
pass
class OldFashionedPrinter(Machine):
def print(self, document):
# ok - print stuff
pass
def fax(self, document):
pass # do-nothing
def scan(self, document):
"""Not supported!"""
raise NotImplementedError('Printer cannot scan!')
class Printer:
@abstractmethod
def print(self, document): pass
class Scanner:
@abstractmethod
def scan(self, document): pass
# same for Fax, etc.
class MyPrinter(Printer):
def print(self, document):
print(document)
class Photocopier(Printer, Scanner):
def print(self, document):
print(document)
def scan(self, document):
pass # something meaningful
class MultiFunctionDevice(Printer, Scanner): # , Fax, etc
@abstractmethod
def print(self, document):
pass
@abstractmethod
def scan(self, document):
pass
class MultiFunctionMachine(MultiFunctionDevice):
def __init__(self, printer, scanner):
self.printer = printer
self.scanner = scanner
def print(self, document):
self.printer.print(document)
def scan(self, document):
self.scanner.scan(document)
printer = OldFashionedPrinter()
printer.fax(123) # nothing happens
printer.scan(123) # oops!