在Python中描述模块和类的正确方法是什么?

时间:2013-05-28 01:44:21

标签: python class module

我是Python的新手,我开始学习代码结构的基础知识。我有一个基本的应用程序,我正在up on my Github

对于我的简单应用程序,我创建了一个基本的“Evernote-like”服务,允许用户创建和编辑笔记列表。在早期的设计中,我有一个Note对象和一个Notepad对象,它实际上是一个音符列表。目前,我有以下文件结构:

Notes.py
| 
|------ Notepad (class)
|------ Note (class)

从我目前的理解和实现,这转换为具有Notepad类和Note类的“Notes”模块,因此当我进行导入时,我说“来自Notes导入记事本/来自Notes导入注释”。

这是正确的做法吗?我觉得,出于Java习惯,我应该有一个Notes文件夹和两个类作为单独的文件。

我的目标是了解最佳做法是什么。

2 个答案:

答案 0 :(得分:4)

只要类很小就把它们放到一个文件中。 如有必要,您仍可以稍后移动它们。 实际上,较大的项目具有相当深的层次结构但是向用户展示更平坦的层次结构是相当普遍的。因此,如果您稍后移动但仍希望notes.Note即使课程Note移动得更深,那么只需将note.path.to.module.Note导入notes并且用户可以从那里得到它。你不必这样做,但你可以。因此,即使您稍后改变主意但想保留API,也没问题。

答案 1 :(得分:1)

我自己一直在使用类似的应用程序。我不能说这是最好的方法,但它对我很有帮助。这些类用于在用户发出请求时与数据库(上下文)进行交互(http请求,这是一个webapp)。

# -*- coding: utf-8 -*-
import json
import datetime

class Note ():
    """A note. This class is part of the data model and is instantiated every
    time there access to the database"""
    def __init__(self, noteid = 0, note = "", date = datetime.datetime.now(), context = None):
        self.id = noteid
        self.note = note
        self.date = date
        self.ctx = context #context holds the db connection and some globals

    def get(self):
        """Get the current object from the database. This function needs the
        instance to have an id"""
        if id == 0:
            raise self.ctx.ApplicationError(404, ("No note with id 0 exists"))
        cursor = self.ctx.db.conn.cursor()
        cursor.execute("select note, date from %s.notes where id=%s" % 
                       (self.ctx.db.DB_NAME, str(self.id)))
        data = cursor.fetchone()
        if not data:
            raise self.ctx.ApplicationError(404, ("No note with id " 
                                                 + self.id + " was found"))
        self.note = data[0]
        self.date = data[1]
        return self

    def insert(self, user):
        """This function inserts the object to the database. It can be an empty
        note. User must be authenticated to add notes (authentication handled
        elsewhere)"""
        cursor = self.ctx.db.conn.cursor()
        query = ("insert into %s.notes (note, owner) values ('%s', '%s')" % 
                       (self.ctx.db.DB_NAME, str(self.note), str(user['id'])))
        cursor.execute(query)
        return self

    def put(self):
        """Modify the current note in the database"""
        cursor = self.ctx.db.conn.cursor()
        query = ("update %s.notes set note = '%s' where id = %s" % 
                 (self.ctx.db.DB_NAME, str(self.note), str(self.id)))
        cursor.execute(query)
        return self

    def delete(self):
        """Delete the current note, by id"""
        if self.id == 0:
            raise self.ctx.ApplicationError(404, "No note with id 0 exists")
        cursor = self.ctx.db.conn.cursor()
        query = ("delete from %s.notes where id = %s" % 
                 (self.ctx.db.DB_NAME, str(self.id)))
        cursor.execute(query)

    def toJson(self):
        """Returns a json string of the note object's data attributes"""
        return json.dumps(self.toDict())

    def toDict(self):
        """Returns a dict of the note object's data attributes"""
        return {
                "id" : self.id,
                "note" : self.note,
                "date" : self.date.strftime("%Y-%m-%d %H:%M:%S")
                }


class NotesCollection():
    """This class handles the notes as a collection"""
    collection = []
    def get(self, user, context):
        """Populate the collection object and return it"""
        cursor = context.db.conn.cursor()
        cursor.execute("select id, note, date from %s.notes where owner=%s" % 
                       (context.db.DB_NAME, str(user["id"])))
        note = cursor.fetchone()
        while note:
            self.collection.append(Note(note[0], note[1],note[2]))
            note = cursor.fetchone()
        return self

    def toJson(self):
        """Return a json string of the current collection"""
        return json.dumps([note.toDict() for note in self.collection])

我个人使用python作为“完成它”的语言,不要打扰自己的细节。这显示在上面的代码中。但是有一条建议:python中没有私有变量和方法,所以不要费心去创建它们。让您的生活更轻松,编码更快,完成任务

用法示例:

class NotesCollection(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        """Retrieve all notes from the current user and return a json object"""
        allNotes = Note.NotesCollection().get(self.get_current_user(), settings["context"])
        json = allNotes.toJson()
        self.write(json)

    @protected
    @tornado.web.authenticated
    def post(self):
        """Handles all post requests to /notes"""
        requestType = self.get_argument("type", "POST")
        ctx = settings["context"]
        if requestType == "POST":

            Note.Note(note = self.get_argument("note", ""), 
                      context = ctx).insert(self.get_current_user())
        elif requestType == "DELETE":
            Note.Note(id = self.get_argument("id"), context = ctx).delete()
        elif requestType == "PUT":
            Note.Note(id = self.get_argument("id"),
                              note = self.get_argument("note"),
                              context = ctx).put()
        else:
            raise ApplicationError(405, "Method not allowed")

通过使用装饰器,我从主代码中获取用户身份验证和错误处理。这使得它更清晰,更容易保持。