python面向对象的使用限制探究

460次阅读
没有评论

python面向对象的使用限制探究

很多人认为面向对象不适合使用,我不认为他有什么问题,但至少在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免费测试

相关文章:

版权声明:wuyou2021-04-26发表,共计2845字。
新手QQ群:570568346,欢迎进群讨论 Python51学习