1
  1. Trying to create a dynamic class property, however, when called on instances an error is thrown. And when called on the class, an unknown object is returned.

I believe the issue is with the understanding of how classmethod is defined.

class Warehouse:
   def __init__(self, inventory_count):
       self.inventory_count = inventory_count

class Shop:
   warehouse = Warehouse(5)

   @property
   @classmethod
   def iv_count(cls):
      return cls.warehouse.inventory_count

s = Shop()

print s.iv_count

Error message:

Traceback (most recent call last):  
    File "main.py", line 15, in <module>
    print s.iv_count
TypeError: 'classmethod' object is not callable

Info:

print Shop.iv_count # <property object at 0x7f5f880d12b8>
  1. Where can I find the source code for python functions, staticmethod and similarly classmethod?
thecartesianman
  • 745
  • 1
  • 6
  • 15
  • 4
    What is a dynamic static property? – wwii Dec 18 '19 at 17:29
  • 1
    I would question the design. It is wrong to do this as staticmethod on the shop class. Use *instances* of Warehouse and Shop instead. Beyond that, the technical reason for this not working is the descriptor protocol. It requires at least a classmethod. But even then it might not work out of the box, I at least have written a classproperty-decorator in the past. – deets Dec 18 '19 at 17:31
  • Related:[Can someone explain how the source code of staticmethod works in python](https://stackoverflow.com/questions/31916048/can-someone-explain-how-the-source-code-of-staticmethod-works-in-python) – wwii Dec 18 '19 at 17:33
  • @deets This is not the actual situation, it's quite hard to demonstrate the real need. But thanks, i'll take a lot at the protocol you mentioned. – thecartesianman Dec 18 '19 at 17:34
  • 1
    Strictly speaking, `staticmethod` and `classmethod` are built-in types, not functions. Their purpose is to provide different definitions of `__get__` than `function` provides (and `function.__get__` is the basis for how instance methods work). – chepner Dec 18 '19 at 17:36
  • For starters your going to want to use new-style classes. And ideally just use Python 3 – juanpa.arrivillaga Dec 18 '19 at 18:08

1 Answers1

2

Learn how to use classes properly first. Don't use a class as if it were, effectively, the only instance of a class. Static methods, in particular, are not used as often as you might think.

# There can be multiple warehouses, each with their own inventory
class Warehouse:
    def __init__(self):
        self.inventory_count = 5


# Every shop has exactly one warehouse it can order from
class Shop:
    def __init__(self, warehouse):
        self.warehouse = warehouse

    # A shop's inventory count is simply the inventory
    # count of its warehouse
    @property
    def iv_count(self):
        return self.warehouse.inventory_count


# Create a warehouse
w = Warehouse()

# Create a shop that uses that warehouse
s = Shop(w)

# Now we can ask about the inventory of the shop
print(s.iv_count)
martineau
  • 119,623
  • 25
  • 170
  • 301
chepner
  • 497,756
  • 71
  • 530
  • 681
  • I understand where you're coming from, but this is not helpful. The actual situation I have is a lot different. What I would like is a way static properties dynamic. Currently, I can leave out the @staticmethod and not use self. But I would like to work out if this can be done cleaner. – thecartesianman Dec 18 '19 at 17:44
  • 2
    You still haven't explained what you mean by "dynamic static property". Post something that *isn't* a lot different form what you have now in the question. This is looking very much like an [XY problem](http://xyproblem.info). – chepner Dec 18 '19 at 17:51
  • Dynamic property: executes logic when the property is accessed. For example, storing date of birth, then having age as a property that is calculated when accessed. Class property, is when the property only accesses elements of the class and not the instance (in python likely with @classmethod). Static property, doesn't neccessarily access the class and cannot access the instance (in python likely with @staticmethod). – thecartesianman Dec 18 '19 at 17:55
  • 1
    That's *all* properties. – chepner Dec 18 '19 at 17:56
  • 2
    Instances of neither `classmethod` nor `staticmethod` are callable; the thing returned by their `__get__` methods when you access them via attribute lookup is. A property-like class method would just be a property of a metaclass, but that's almost certainly more work than is necessary. A static method is just a function that happens to be bound to a class attribute; I can't think of a good reason to prefer `A.foo` to `A.foo()`. – chepner Dec 18 '19 at 18:00
  • 3
    One rationale for providing properties in the first place is as follows. You originally define a class that exposes an instance attribute directly: `print(foo.bar)`, `foo.bar = 3`, etc. Then one day, you decide you want to provide some restrictions on how that attribute is used. You could write getter and setter methods, but that changes the interface and either breaks existing code or requires users of the class to update. A property lets you introduce the setters in a backwards-compatible manner; `print(foo.bar)` and `foo.bar = 3` continue to work as before, but invoke methods now. – chepner Dec 18 '19 at 18:03
  • 2
    The above use case doesn't extend in any meaningful way to class or static methods. – chepner Dec 18 '19 at 18:03