很多人认为面向对象不适合使用,我不认为他有什么问题,但至少在Python中不需要。
1、不需要使用面向对象。
举个例子,例如下面的代码根本不需要使用面向对象。
class ApiClient: def __init__(self, root_url: str, session_cls: sessionmaker): self.root_url = root_url self.session_cls = session_cls def construct_url(self, entity: str) -> str: returnf"{self.root_url}/v1/{entity}" def get_items(self,entity: str) -> List[Item]: resp = requests.get(self.construct_url(entity)) resp.raise_for_status() return [Item(**n) for n in resp.json()["items"]] def save_items(self, entity: str) -> None: with scoped_session(self.session_cls)as session: session.add(self.get_items(entity)) class ClientA(ApiClient): def construct_url(self, entity: str) -> str: returnf"{self.root_url}/{entity}" class ClientB(ApiClient): def construct_url(self, entity: str) -> str: returnf"{self.root_url}/a/special/place/{entity}" client_a = ClientA("https://client-a",session_cls) client_a.save_items("bars")
我们在这里使用了面向对象,因为我们想把root_url绑定到某个对象,我们不想每次都传递sessionmaker。我们还想使用继承,在调用的途中访问一种方法。
但是,只有数据传输和函数才能实现吗?
@dataclass class Client: root_url: str url_layout: str client_a = Client( root_url="https://client-a", url_layout="{root_url}/{entity}", ) client_b = Client( root_url="https://client-b", url_layout="{root_url}/a/special/place/{entity}", ) def construct_url(client: Client, entity: str) -> str: returnclient.url_layout.format(root_url=client.root_url, entity=entity) def get_items(client: Client, entity: str) -> List[Item]: resp = requests.get(construct_url(client, entity)) resp.raise_for_status() return [Item(**n) for n in resp.json()["items"]] def save_items(client: Client, session_cls: session_cls, entity: str) -> None: withscoped_session(session_cls) as session: session.add(get_items(client, entity)) save_items(client_a,session_cls, "bars")
必须随时传达Client和session_cls。
但是有什么关系呢?代码量甚至减少了10%。这样写出来的代码很容易理解,不需要使用对象。
有人管理这种写法叫做函数袋。也就是说,整个代码由有类型的数据和很多模块作用域的函数构成。
那么,全局变量如何处理呢?您可以参考本文(https://leontrolski.github.io/sane-config.html),在整个应用程序的生命周期内重用config或db的session。
界面、抽象类怎么办?其实你不需要它们,直接写代码就可以了。从平心来看,Python有类型标记后,函数袋的风格开始发挥真正的魅力。
不纯粹的函数怎么办?
如果您想使用纯函数编程,您可能想编写纯类别,然后使用不纯的适配器例子进行一些处理:getting-the-curent-datetime/API-calls/talking-to-the-db/other-impure-stuff。这个想法很好。事实上,你可以直接使用freezegun、responses等方法来避免大量的麻烦。
2、例外。
但是,也有例外的情况
你可能注意到,重构的代码中加入了@dataclass,它们只是记录类型。Python3可直接支持这些,无需使用套路类。
使用Exception的子类没问题。使用try:..exceptSomeClass:..基本上形成层次,但没关系。不要太复杂。
Enum和上面一样,非常适合Python。
在极其罕见的情况下(至少在应用程序开发中很少见),你可能会想到一种非常有用的类型,然后到处使用ndas.DataFrame/sqlalchemy.Session一样。但一般来说,不要欺骗自己,也不要欺骗自己,说我们正在建立一个伟大的应用程序。谦虚使人进步。
3、面向对象的弊端。
在这篇文章的开头,我说对方本身没有什么问题,其实对方不仅没有帮助,还经常混淆问题,鼓励不好的做法
鼓励对方修改数据。函数非常反对修改参数。如果你不相信,你可以试试,但不要生气。
面向对象只是回归的全局变量。无法在函数之间共享数据。self强制使用更小的状态空间制作容易测试的函数。
混合数据和函数会加剧序列化的难度,而在当今RESTAPI流行的情况下,序列化是非常有用的。
面向对象带来疯狂的继承体系统,关于这个话题的讨论遍地都是。
最重要的是,对象没有附加价值,只能集中解决问题,加剧阅读和理解代码的难度。
神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试