Python中传递对象属性到函数的最常用方法是什么?

3

我相信我虽然做得出来,但是我的方法并不正确。现在,当我调用一个函数时,我只是传递整个对象,例如:

class my_file_obj:
    def __init__(self,filename):
        self.filename = filename
        self.owner = None
        self.file_type = None
        self.fileflag = 0
        self.md5 = None

以下是一个函数调用,其中 file_obj1my_file_obj 的一个实例:

some_function(file_obj1)

然后根据需要在函数内引用所需的属性。

这应该采用什么样的“python”/正确方式呢?

  • some_function(file_obj1)

  • some_function(file_obj1.filename)

  • the_filename = file_obj1.filename
    some_function(the_filename)

1
这完全由您自行决定。您是否仅需要使用文件名?您是否有传递不带对象的文件名的情况? - Rafe Kettler
@RafeKettler:我认为那已经足够作为一个回答了。 - Blender
不确定在Python中直接访问对象的数据成员是否被推荐。您可以使用访问函数,例如def getFilename(self)或类似的内容(请参见http://en.wikipedia.org/wiki/Mutator_method获取更多信息)。 - hochl
5个回答

5

很明显,这取决于some_function是需要整个对象还是只需要文件名,如果只需要文件名,则传递整个my_file_obj实例或只传递文件名。


感谢回复。我不确定Python是否有接口,或者获取器类型函数是否是首选方法。我假设传递整个对象会更加消耗内存/计算资源,对吗? - user982599
1
@user982599:Python中的所有名称都是引用。唯一的区别在于属性查找时间(foo vs foo.bar),但这可能是可以忽略不计的。 - Cat Plus Plus
我没有基准测试数据,但实际上你所做的是将对象实例的引用传递给函数,而不是对象本身。因此,这样做在计算上不应该更加耗费资源。 - ZenGyro

1

所有的方法都是可以接受的,你选择哪种方法将取决于你的应用(或设计)选择。

# with this call the file_obj1 object reference is sent to some_function()
some_function(file_obj1)

# with this call there is no pass by reference. If filename is a 
# string it is copied to some_function
some_function(file_obj1.filename)

# same as before, but here you are allocating a new var and copying the content
# to some_function
the_filename = file_obj1.filename
some_function(the_filename)

从技术上讲,这是误导性的 - Python实际上是按对象调用的。在您的第二个示例中,您仍然传递实际的字符串对象,但它恰好是不可变的,不像file_obj1实例。 - Wayne Werner

1

我认为some_function(file_obj1)是最符合Python风格的。

some_function(file_obj1.filename)并没有将对象传递给函数,它只传递了文件名属性作为字符串。这将需要大量琐碎的代码来获取对象的其余属性。


0
或者您可以在您的类中添加一个def __str__(self): return self.filename方法(因为也许在您的设计中,打印文件对象应该返回其名称),并接受任何类型的对象作为您的函数参数。例如,该函数看起来像这样:
def openFile(obj):
    return open(str(obj), 'rU')

像这样,该函数接受字符串和您的类的对象。请参见http://en.wikipedia.org/wiki/Duck_typing

不确定是否建议使用此设计--只是想指出一些不太明显的东西。也许这甚至符合Pythonic风格?


0

嗯,这取决于你想做什么和你的目标是什么。

如果你有一个类似于这样的函数:

def some_function(file_thingy):
   with open(file_thingy.filename, 'w') as f:
       f.write("Icky Icky Icky Patang NeeeeWom!")

这样做会使事情变得更加通用 - 只要传入一个具有字符串属性.filename的对象,您的函数就可以工作。这种情况的一个更常见的例子是人们谈论鸭子类型。如果它看起来像一只鸭子,走起路来像一只鸭子,嘎嘎叫起来像一只鸭子,那么它就是一只鸭子!

因此,如果您有以下函数:

def do_duck_things(a_duck):
    print(a_duck.appearance)
    a_duck.waddle()
    a_duck.quack()
    print("It must be a duck!")

然后你可以传递一个实例:

class Duck:
    def __init__(self):
        self.appearance = "White, like the AFLAC duck"

    def quack(self):
        print("Quaaaaaack!")

    def waddle(self):
        print("The duck waddles.")

或者这些类的实例:

class UglyDuckling:
    def __init__(self):
        self.appearance = "Suspiciously like a baby goose"

    def waddle(self):
        print("The ugly duckling waddles a bit like a duck.")

    def quack(self):
        print("Hoooonk!")

class Human:
    def __init__(self):
        self.appearance = "Looks like a human in a duck costume"

    def waddle(self):
        print("Surprisingly, he waddles quite like a duck.")

    def quack(self):
        print("<A sound quite like Donald Duck would make>")

所以在你的情况下,这真的取决于你的函数应该做什么。如果它所做的只是读取文件的内容,那么你可以(而且可能应该)只发送一个文件名。但是,如果你想做一些像检查文件与存储的MD5是否相符或设置MD5之类的事情,那么传入对象是完全适当的。

希望对你有所帮助


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接