user982599
user982599

Reputation: 975

What is the most preferred way to pass object attributes to a function in Python?

I am certain I am doing this "incorrectly" even though it works. Right now when I call a function I just pass the whole object i.e.

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

The function call, where file_obj1 is an instance of my_file_obj:

some_function(file_obj1)

and then referencing the attributes I need as needed within the function.

What is the "python"/correct way of doing this?

Upvotes: 3

Views: 1595

Answers (5)

hochl
hochl

Reputation: 12920

Or you may add a def __str__(self): return self.filename method to your class (because, maybe, printing a file object should return its name in your design anyways) and accept any kind of object for your function. The function then, for example, looks like this:

def openFile(obj):
    return open(str(obj), 'rU')

Like this, the function accepts both strings and objects of your class. See http://en.wikipedia.org/wiki/Duck_typing.

Not sure if this design is recommended -- just want to point out something less obvious. Maybe this is even pythonic?

Upvotes: 0

Wayne Werner
Wayne Werner

Reputation: 51797

Well, it depends on what you want to do and what your goal is.

If you have a function that looks something like this:

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

Then it makes things much more generic - as long as you pass an object in that has a .filename attribute that is a string then your function will work. A more common example of this is when people talk about duck typing. If it looks like a duck, walks like a duck, and quacks like a duck, well then it's a duck!

So if you have the following function:

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

Then you could pass it an instance of:

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

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

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

or an instance of either of these classes:

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>")

So in your case, it really depends on what your function should be doing. If all it's doing is reading the contents of a file, then you can (and probably should) just send it a filename. But if you want to do something like, say, check the file against your stored MD5, or set that MD5, then it's perfectly appropriate to pass in the object.

HTH

Upvotes: 0

Carlo Pires
Carlo Pires

Reputation: 4916

All the ways are acceptable and which you will choose will depend on your application (or design) choices.

# 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)

Upvotes: 1

ZenGyro
ZenGyro

Reputation: 176

I think some_function(file_obj1) is the most pythonic.

some_function(file_obj1.filename) doesn't pass the object to the function, it only passes the filename attribute as a string. It then would require a lot of fiddly code to get the rest of the object's attributes.

Upvotes: 1

Cat Plus Plus
Cat Plus Plus

Reputation: 129764

Well, it's quite obvious. It depends on whether some_function needs the whole object or just the filename, in which case you pass the whole my_file_obj instance or just the filename.

Upvotes: 5

Related Questions