Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8324383
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 9, 20262026-06-09T00:03:02+00:00 2026-06-09T00:03:02+00:00

tl;dr: How come property decorators work with class-level function definitions, but not with module-level

  • 0

tl;dr: How come property decorators work with class-level function definitions, but not with module-level definitions?

I was applying property decorators to some module-level functions, thinking they would allow me to invoke the methods by mere attribute lookup.

This was particularly tempting because I was defining a set of configuration functions, like get_port, get_hostname, etc., all of which could have been replaced with their simpler, more terse property counterparts: port, hostname, etc.

Thus, config.get_port() would just be the much nicer config.port

I was surprised when I found the following traceback, proving that this was not a viable option:

TypeError: int() argument must be a string or a number, not 'property'

I knew I had seen some precedant for property-like functionality at module-level, as I had used it for scripting shell commands using the elegant but hacky pbs library.

The interesting hack below can be found in the pbs library source code. It enables the ability to do property-like attribute lookups at module-level, but it’s horribly, horribly hackish.

# this is a thin wrapper around THIS module (we patch sys.modules[__name__]).
# this is in the case that the user does a "from pbs import whatever"
# in other words, they only want to import certain programs, not the whole
# system PATH worth of commands.  in this case, we just proxy the
# import lookup to our Environment class
class SelfWrapper(ModuleType):
    def __init__(self, self_module):
        # this is super ugly to have to copy attributes like this,
        # but it seems to be the only way to make reload() behave
        # nicely.  if i make these attributes dynamic lookups in
        # __getattr__, reload sometimes chokes in weird ways...
        for attr in ["__builtins__", "__doc__", "__name__", "__package__"]:
            setattr(self, attr, getattr(self_module, attr))

        self.self_module = self_module
        self.env = Environment(globals())

    def __getattr__(self, name):
        return self.env[name]

Below is the code for inserting this class into the import namespace. It actually patches sys.modules directly!

# we're being run as a stand-alone script, fire up a REPL
if __name__ == "__main__":
    globs = globals()
    f_globals = {}
    for k in ["__builtins__", "__doc__", "__name__", "__package__"]:
        f_globals[k] = globs[k]
    env = Environment(f_globals)
    run_repl(env)

# we're being imported from somewhere
else:
    self = sys.modules[__name__]
    sys.modules[__name__] = SelfWrapper(self)

Now that I’ve seen what lengths pbs has to go through, I’m left wondering why this facility of Python isn’t built into the language directly. The property decorator in particular seems like a natural place to add such functionality.

Is there any partiuclar reason or motivation for why this isn’t built directly in?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-09T00:03:03+00:00Added an answer on June 9, 2026 at 12:03 am

    This is related to a combination of two factors: first, that properties are implemented using the descriptor protocol, and second that modules are always instances of a particular class rather than being instantiable classes.

    This part of the descriptor protocol is implemented in object.__getattribute__ (the relevant code is PyObject_GenericGetAttr starting at line 1319). The lookup rules go like this:

    1. Search through the class mro for a type dictionary that has name
    2. If the first matching item is a data descriptor, call its __get__ and return its result
    3. If name is in the instance dictionary, return its associated value
    4. If there was a matching item from the class dictionaries and it was a non-data descriptor, call its __get__ and return the result
    5. If there was a matching item from the class dictionaries, return it
    6. raise AttributeError

    The key to this is at number 3 – if name is found in the instance dictionary (as it will be with modules), then its value will just be returned – it won’t be tested for descriptorness, and its __get__ won’t be called. This leads to this situation (using Python 3):

    >>> class F:
    ...    def __getattribute__(self, attr):
    ...      print('hi')
    ...      return object.__getattribute__(self, attr)
    ... 
    >>> f = F()
    >>> f.blah = property(lambda: 5)
    >>> f.blah
    hi
    <property object at 0xbfa1b0>
    

    You can see that .__getattribute__ is being invoked, but isn’t treating f.blah as a descriptor.

    It is likely that the reason for the rules being structured this way is an explicit tradeoff between the usefulness of allowing descriptors on instances (and, therefore, in modules) and the extra code complexity that this would lead to.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

More often than I'd have hoped I seem to come across method/property definitions in
I have come across a class that has an immutable property: MyObject[] allObjs The
I want to filter a property within a range, but items that does not
How come the following works? print Property is : . $property->name(NODE_HOST) . \n; but
I have a property which is an array of items, but when I come
I have come across code in the form: MyClass.class.getName(); Is .class a property? Is
I've come across a difficult to track bug, but I'm not sure what is
I want to extend my EF class with additional property that would come from
I'm want to use RedirectAttibutes property that has come up in Spring 3.1, I
Come across what looks at first sight like an MT-issue, but I'm trying to

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.