chyyran
chyyran

Reputation: 2636

How to get an attribute of a function without calling the function

Say I have a function like so

def spam():
    spam.eggs = "Foobar"
    #do stuff
    return

I want to get the value of spam.eggs ("Foobar") in another function without having to actually call the spam() method, for example,

def main():
  print spam.eggs

and I want it to return Foobar. However, obviously, this wouldn't work, since I haven't called spam() yet, so I've never assigned the spam.eggs property, so I'd have to do this

def main():
    spam()
    print spam.eggs

However, I don't want to call the spam() function if I want the eggs attribute, in fact, I want to check whether spam() has the eggs attribute, and if it equals "Foobar" before calling it, for example

def main():
    if hasattr(spam,'eggs'):
        if getattr(spam, 'eggs') == "Foobar":
            spam()

But like before, since I haven't called spam I haven't assigned spam.eggs yet.

Is there any way to do this, perhaps with a decorator? I want to keep the assignment somewhat close to the function, so I'd prefer something that's not like

def func():
    setattr(spam, 'eggs', 'Foobar')

Where I have to do setattr() in another method, unless in a decorator.

Upvotes: 1

Views: 566

Answers (3)

PuercoPop
PuercoPop

Reputation: 6807

You would get the attribute with spam.eggs plain and simple. Btw you don't have to be inside the function to assign the attribute. You could do

def spam():
    #do stuff
    return
spam.eggs = "Foobar"

and then spam.eggs and spam() would work exactly the same

Upvotes: 1

BrenBarn
BrenBarn

Reputation: 251408

It could be done with a decorator, yes:

def addEggs(func):
    func.eggs = "foobar"
    return func

@addEggs
def spam():
    pass

>>> spam.eggs
'foobar'

If you want to be able to specify the attribute name and/or value in a parameterized way, you'd have to write a more complex decorator:

def addAttr(attr, value):
    def deco(func):
        setattr(func, attr, value)
        return func
    return deco

@addAttr('attrName', 'value')
def spam():
    pass

>>> spam.attrName
'value'

However, there's still the question of why you want to do this. If function attributes are useful at all, it's usually because there's a natural place to set them --- that is, something else sets attributes on functions for its own purposes. If you're just setting the attribute right when you define the function --- that is, if the attributes are an intrinsic part of the function itself --- it seems like you might want something more like a class with a method.

Upvotes: 4

Joran Beasley
Joran Beasley

Reputation: 113988

I think you actually want a class with static fields. since variables are local to the function they are declared in there is no way to access them the way you want to

class Spam:
     eggs="foobar"
     def __init__(self,*args,**kwargs):
         # do some stuff
         Spam.eggs = "foobared"

print Spam.eggs
Spam()
print Spam.eggs

Upvotes: 1

Related Questions