0

I have a question regarding how the following segment of code runs (i.e. the code is copied over from a response Andy Hayden gave on this question: "How do convert a pandas/dataframe to XML?")

def to_xml(df, filename=None, mode='w'):
    def row_to_xml(row):
        xml = ['<item>']
        for i, col_name in enumerate(row.index):
            xml.append('  <field name="{0}">{1}</field>'.format(col_name, row.iloc[i]))
        xml.append('</item>')
        return '\n'.join(xml)
    res = '\n'.join(df.apply(row_to_xml, axis=1))

    if filename is None:
        return res
    with open(filename, mode) as f:
        f.write(res)

pd.DataFrame.to_xml = to_xml

Then, assuming you have a Pandas dataframe object (df), the to_xml function can be called by running:

df.to_xml()

or

df.to_xml('foo.xml')

What I don't understand is why when calling df.to_xml am I not required to pass in the instance of my dataframe object as an argument to the function since the first parameter is not optional?

More clearly, why am I not required to call to_xml in the following ways?:

df.to_xml(df)

or

df.to_xml(df, 'foo.xml')

Thanks in advance

DGav
  • 271
  • 3
  • 14
  • 1
    Because you first do an implicit `getattr(df,'to_xml')` call which produces a "new" function that passes the object as first argument implicitly. – Willem Van Onsem Oct 19 '17 at 19:24
  • @Jean-FrancoisFabre: I think the OP wants to know why the first argument is an "implicit" one. – Willem Van Onsem Oct 19 '17 at 19:25
  • @WillemVanOnsem I think I've missed the point... – Jean-François Fabre Oct 19 '17 at 19:25
  • Accessing `df.to_xml` produces a bound method object that knows how to insert `self`; the access doesn't directly give you the function you defined. – user2357112 Oct 19 '17 at 19:26
  • Because you add the function to the class, `pd.DataFrame.to_xml = to_xml`, it is now a method, and will get the instance passed to it implicitly when accessed form an instance. The same as if you had written this in a class definition – juanpa.arrivillaga Oct 19 '17 at 19:32
  • @WillemVanOnsem Oh that makes perfect sense. And just for further clarification, this process of producing this "new" function that passes the object as the first argument implicitly happens with every function call in python? – DGav Oct 19 '17 at 19:47
  • @DGav: no, you have `@classmethod` and `@staticmethod` decorators such that this procedure is ommitted. Furthermore it does *not* happen when you call the function, it happens when you *fetch* the function. – Willem Van Onsem Oct 19 '17 at 19:48
  • @juanpa.arrivillaga okay, that answers my clarification question. Thanks! – DGav Oct 19 '17 at 19:48

0 Answers0