@ShivamKotwalia's answer is what you're looking for, but since it seems you are trying to understand why your implementation didn't work, I'll expand a little bit.
Currently your implementation is creating nested functions in the local scope. In another word, once the code is outside of the function the objects inside the local scope cease to exist unless return
ed to the outer scope. Take for instance a modification of your code:
def GetAttributes(person):
def GetName(person):
return person.name
def GetSurname(person):
return person.surname
return GetName, GetSurname
This allows you to reference back to GetName
and GetSurname
now because they have been passed back to the outer scope. Assuming you have a Bob
object that has the attribute name
and surname
:
name = GetAttributes(Bob)
name
# (<function GetAttributes.<locals>.GetName at 0x03E9AB28>, <function GetAttributes.<locals>.GetSurname at 0x03E9AB70>)
Notice how name
has the two inner functions passed in, and that they are <locals>
. Whereas GetAttributes
is under the global
scope: <function GetAttributes at 0x03E9AA50>
.
You can then get the two functions by the index of name
:
name[0](Bob)
# Bobby
name[1](Bob)
# Tables
Notice again how you still require Bob
to be passed in, because both functions were defined as requiring the argument person
. You could opt to remove the arguments...:
def GetAttributes(person):
def GetName():
return person.name
def GetSurname():
return person.surname
return GetName, GetSurname
But then you're still faced with a few problems:
- You first have to assign an object for the function to access the inner functions.
- The
GetAttributes
function return nothing but its inner functions.
- The access to the local functions are not meaningfully structured.
- There's no guarantee that the object you pass in will always have
name
and surname
attributes.
That's why the OOP approach (e.g. class
) and methods
exist:
class Person:
def __init__(self, name, surname):
self.name = name
self.surname = surname
def GetName(self):
return self.name
def GetSurname(self):
return self.surname
This address all the issues above as you now have:
- You just need to create an instance of the
Person
class
instead of messy function handling.
GetAttributes
is not necessary any more.
- Easy and meaningful access to get
Person().GetName()
.
- The objects using these
methods
are guaranteed to have name
and surname
attributes.
"But what about the GetAttributes
method?" you ask? Why, Python does have a built-in getattr()
function that will serve your need!
getattr(Bob, 'name')
# Bobby
Having said all that, there does exist function attributes
where you can do something like this:
def GetAttributes(person):
def GetName():
return person.name
def GetSurname():
return person.surname
GetAttributes.GetName = GetName
GetAttributes.GetSurname = GetSurname
return GetAttributes
GetAttributes(Bob).GetName()
# Bobby
But you very quickly run into limitations and problems managing all the objects and functions you might pass within the scopes. Try it and you will see. Thus, why would you opt to go through this trouble when class
, getattr
and methods
already do everything that you need with the benefits of safeguards in place?