从小脚本过渡到更大的应用程序并不容易

kol*_*bos 5 python

我相信可读性和KISS原则是编程中最重要的事情.这就是为什么我使用Python :)
这是确切的情况,我经常遇到:

说,我有一个漂亮而干净的脚本,它是数据库处理的包装器:

import database_schema as schema
loader = schema.Loader("sqlite:///var/database.db")
session = loader.session

def addUser(name, full_name, password):
    user = schema.User(name, full_name, password)
    session.add(user)
    session.commit()

def listUsers():
    all_users = session.query(schema.User).all()
    return all_users
Run Code Online (Sandbox Code Playgroud)

使用方式如下:

import database
database.addUser("mike", "Mike Driscoll", "password")
database.listUsers()
Run Code Online (Sandbox Code Playgroud)

在某些时候,我想重写该模块,以便它可以在不同的路径上使用数据库(例如,用于单元测试).

那么,我的选择是什么?

  1. 最直观的是添加database_path == ""变量,然后......什么?使用setPath(new_path)函数设置它,然后将exception(if database_path == "": raise SomeException)添加到每个函数中,这只是丑陋的,任何人都不应该这样做.

  2. 全功能类,设置self._database_path初始化时间.

然后以这种方式使用:

from database import Database
database = Database("sqlite:///var/database.db")
database.addUser("mike", "Mike Driscoll", "password")
database.listUsers()
Run Code Online (Sandbox Code Playgroud)

这已经是比第一个例子更多的代码行,并且增加了命名问题:Database在模块中调用一个类database是愚蠢的,不是吗?

很抱歉长时间阅读,这里是我的最后一个问题:

  1. 为什么__init__在Python中没有模块函数这样的东西?
  2. 我是否遗漏了某些东西(静态类变量等),它可以做我想要的(导入时的常量设置)简单而干净的方式,离一个带有一堆简单函数的模块还不远首先?

对不起我的英语.

编辑:

所以,为了清楚说明,这个代码在我富有想象力的Python世界中会是什么样子:

import database_schema as schema

def __init__(database_path):
    loader = schema.Loader(database_path)
    global session
    session = loader.session

def addUser(name, full_name, password):
    user = schema.User(name, full_name, password)
    session.add(user)
    session.commit()

def listUsers():
    all_users = session.query(schema.User).all()
    return all_users
Run Code Online (Sandbox Code Playgroud)

像这样使用:

import database("sqlite:///var/database.db")

database.addUser("mike", "Mike Driscoll", "password")
database.listUsers()
Run Code Online (Sandbox Code Playgroud)

pyf*_*unc 2

模块是一个 Python 对象,具有可以绑定和引用的任意命名的属性。名为 mod 的模块的 Python 代码通常驻留在名为 mod.py 的文件中。当您尝试导入它时,会创建一个新的命名空间,其中包含该模块的所有属性。

尽管如此,它与类和该类的对象实例的创建不同。这些是不同的抽象,应该这样使用。

而不是测试

if database_path == "":
    ....
Run Code Online (Sandbox Code Playgroud)

做Python式的方式

if database_path:
   ....
Run Code Online (Sandbox Code Playgroud)

您可以使用断言,而不是引发异常

assert database_path != "", 'database path empty'
Run Code Online (Sandbox Code Playgroud)

模块不像类的对象实例那样存在。每次导入模块时,导入模块都会创建一个具有相同属性集的命名空间。在这种情况下,init可能没有多大意义。

您提供的第二种形式的代码没有任何问题。如果您不想这样做,上面的一些习语可能会减轻您的痛苦:)