【问题标题】:Pythonic way of creating a class in python 2.7.6在 python 2.7.6 中创建类的 Pythonic 方式
【发布时间】:2013-11-29 20:48:55
【问题描述】:

我已经定义了一个模块来处理多种类型的数据文件(例如 filetypes.py)。在其中,我定义了一个基类来处理文件打开和一些基本处理,这些基本处理由特定于每种数据文件类型的其余类继承。在每个类中,我使用 __init__() 方法来初始化一些类变量,并使用另一种方法来读取具有作为输入文件名的数据文件(此操作不能在 __init__() 方法中完成)。比如:

class maintype(object):
    """main type class.""
    def __init__(self):
        self.a = 1

class filetype1(maintype):
    """file type 1 class."""
    def __init__(self):
        self.b = 1

    def readfile(self, filename):
        self.ifile = open(filename, 'rb')

从主代码调用这个模块,感觉有点不自然:

import filetypes

data = filetypes.filetype1()
data.readfile('some_file_name')

问题:在模块中定义一个返回类的函数而不是使用类方法不是更pythonic吗?比如:

def file_type1(filename):
    class1 = filetype1()
    class1.readfile(filename)
    return class1

现在,它看起来像:

import filetypes

data = filetypes.file_type1('some_file_name')

我在网上搜索过,找不到任何有用的迹象...

【问题讨论】:

  • 在我们担心 pythonic 之前,您应该首先意识到您使用了不正确的naming conventions 和术语。 maintype 应该是 MainTypereadfile 应该是 read_filereadfile 不是类方法(它是实例方法),函数 file_type1 正在返回类的实例,而不是返回类本身。至于这个问题,有时定义创建对象的函数然后在返回对象之前调用方法很有用。很难说这是否适合您的用例。
  • 您对命名约定和术语是正确的,我对它们并不放心。我应该编辑问题还是保持原样?
  • 现在我已经把我的问题用语言表达出来了,我一直在重新考虑我是否在开发模块的过程中走的是正确的道路。我将重点放在不同类型的文件上,而不是数据上。我正在看的是一个模块,独立于我正在阅读的文件类型,我总是得到相同的底层数据表示(我正在处理来自不同类型传感器/系统的采样数据)。这种另一种设想将使类的设计更加精简。
  • 查看我编辑的答案,很抱歉假设您最初是迟到的,记得点赞并接受。

标签: function class python-2.7 methods


【解决方案1】:

不,a=A() 其中 A 是一个类是“pythonic”方式,__init__ 已经是一个函数。

例如,如果您扩展一个类但不调用基类的__init__s,那么您只会得到它们的功能。

顺便说一句,你可以将东西传递给构造函数。

例如:

class A(object):
     def __init__(self,extra):
          print("Look, extra: ",extra)

我认为 OP 是一个不知道构造函数做了什么的迟到/菜鸟,对此感到抱歉,这是一个更好的答案:

这是一个面向对象的东西,一个函数可以做,但你希望它以某种方式属于你的类,你可以把它们放在同一个 python 包或静态方法中。如果我有一个复数类,我会将 conjugate 设为静态方法,因为它属于复数,但是我会将一些使用复数的东西放在外面,但对于所有复数来说都不重要。

假设我有一个__str__ 函数,显然是在里面,因为每个复数都可以做到这一点。假设我有一个“输入两个数字”函数,它打印出用户输入的复数,这是一个碰巧使用复数的函数,因此不是静态方法或方法。

这是我的例子:

#! /usr/bin/python

class reading_thing_maybe(object):
    def __init__(self,filename=None):
        #usual constructor code
        print "\tConstructor!"

        if not filename is None:
            print "\tSpecial case, constructing but doing readfile right away!"
            self.readfile(filename)

    def readfile(self,filename):
        print "\tReding file:",filename

class other_reading_thing(object):
    def __init__(self):
        print "\tConstructor"

    def readfile(self,filename):
        print "\tReding file:",filename

    @staticmethod
    def read_from_file(filename):
        print "\tconstructing with a read from",filename
        result = other_reading_thing()
        result.readfile(filename)
        return result

if __name__ == "__main__":
    print "normal"
    a = reading_thing_maybe()
    print "assuming constructor takes nothing"
    b = reading_thing_maybe("hello")
    print "using the filename= format"
    c = reading_thing_maybe(filename="use me if constructor takes arguments")
    print "Static method"
    d = other_reading_thing.read_from_file("test")

输出:

alec@ATLaptop ~ $ chmod +x ./example.py 
alec@ATLaptop ~ $ ./example.py 
normal
    Constructor!
assuming constructor takes nothing
    Constructor!
    Special case, constructing but doing readfile right away!
    Reding file: hello
using the filename= format
    Constructor!
    Special case, constructing but doing readfile right away!
    Reding file: use me if constructor takes arguments
Static method
    constructing with a read from test
    Constructor
    Reding file: test
alec@ATLaptop ~ $ 

【讨论】:

  • 就像我在问题中提到的那样,将 __init__() 方法直接读取文件不是一种选择,因为必须先进行其他操作(示例中未显示)。
  • @pxc 静态方法装饰器来做到这一点。您还可以使用命名参数。 def __init__(self,filename=None): 之类的东西,然后是你的构造函数代码,然后是 if not filename is None:,下一行是 self.readfile(filename)
猜你喜欢
  • 1970-01-01
  • 2016-06-05
  • 2013-09-02
  • 1970-01-01
  • 2010-10-29
  • 2019-02-11
  • 1970-01-01
  • 1970-01-01
  • 2012-06-28
相关资源
最近更新 更多