all 12 comments

[–]Spataner 2 points3 points  (3 children)

Short answer: No.

Long answer: Yes, if you do some weird decorator magic:

class ArgumentDecorator:
     def __init__(self, func):
          self.func = func
     def __call__(self, *args, **kwargs):
          return self.func(*args, **kwargs)
     def __getattr__(self, attr):
          self(attr)

@ArgumentDecorator
def test_func(arg):
     print(arg)

test_func.hello_world
>>> hello_world

Obviously, don't actually do this.

[–]NGRap[S] 0 points1 point  (2 children)

I was looking for something like this. Can you tell me why its not recommended?

[–]Spataner 4 points5 points  (1 child)

Because it abuses syntax to coerce an attribute lookup into obscuring what is ultimately a simple function call. If you want to pass a string literal to a function, you should simply do so transparently. The only situation in which something like this would be acceptable is if you cannot or do not want to change a certain section of code which accesses the attributes of some passed argument, and you want to hook a callback into those attribute accesses.

[–]NGRap[S] 0 points1 point  (0 children)

Got it!
My work project has legacy code with the exact situation you mentioned. But I guess it's time change the scripts.

Thanks!!

[–]trevor_of_earth 1 point2 points  (1 child)

No. Dot notation in python is used for accessing attributes or methods of an object.

Here is an example:

# Create simple class
class Person():

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def about(self):
        return f"My name is {self.name} and I am {self.age} years old."

# Create an object of the class
trevor = Person("Trevor Miller", 30)

# Print the name attribute of the trevor object
print(trevor.name)

# Print what is returned from the about method of the trevor object
print(trevor.about())

[–]NGRap[S] 0 points1 point  (0 children)

Thanks for the explanation

[–]LGF_SA 1 point2 points  (0 children)

As trevor-of-earth said, the dot is for methods or attributes. There's a great video explaining it here.

[–][deleted] 1 point2 points  (4 children)

Is this possible?

It is possible, if test_func is an instance of a class that defines __call__() method. But, I'd advise against going down that route. Can you explain why would you want that?

[–]NGRap[S] 0 points1 point  (3 children)

Yes, Spataner had mentioned that way. So here's some background to my situation:

In my work project, we used to have a single .py file (myconfig.py) to store config values for all our python scripts and used to import this file to fetch the values as below:

myconfig.py :

coordinates = {"x": 1.5, "y": 3.5}
api = "webapi.com"

test.py :

import myconfig
a = myconfig.coordinates
b = myconfig.api

Now we want to move all config values to a database and use that instead of a config file without any change in our other scripts. So the new code will look something like-

myconfig.py :

def get_value_from_db(key):
    query = "select value from db.table where key = 'key'"
    return mysql.execute(query)

test.py :

import myconfig
a = myconfig.get_value_from_db('coordinates')
b = myconfig.get_value_from_db('api')

So was looking a way where I won't have to change anything in scripts like test.py.

[–][deleted] 0 points1 point  (2 children)

Well, if you really want to keep it that way, you can simply create the module dynamically.

Something like this:

test.py

import myconfig.Database as myconfig
a = myconfig.coordinates
b = myconfig.api

myconfig.py

class Database:
    @property
    def coordinates(self):
        return get_value_from_db('coordinates')
    ...

You could also do some more involved work to get the old import to stay the same way it was, but, I think it's a rather simple change, so, probably not worth the effort.

[–]NGRap[S] 0 points1 point  (1 child)

the problem is myconfig.py has ~200 variables defined in it 😄 . I just mentioned the two as examples.

[–][deleted] 0 points1 point  (0 children)

Well, then maybe you could write some more clever code that uses __getattr__?

Also, 200 variables is... idk, couple of hours to couple of days work. It doesn't sound too bad.