#๐Ÿ”’ How to create static properties while retaining type information?

20 messages ยท Page 1 of 1 (latest)

pastel oxide
#

From Python 3.9 to 3.11, you could combine @classmethod and @property. However, this is now deprecated.

I found this thread: https://stackoverflow.com/questions/1697501/staticmethod-with-property

Which outlines a few possible solutions.

For example this: https://stackoverflow.com/a/76453871/12834165

class staticproperty(property):
  def __get__(self, owner_self, owner_cls):         
    return self.fget()

class classproperty(property):
  def __get__(self, owner_self, owner_cls):
    return self.fget(owner_cls)

And these work fine. However, I've not been able to implement typing in a way which MyPy accepts.

I'll happily accept alternative solutions as well.

Any help much appreciated ๐Ÿ™‚

manic compassBOT
#

@pastel oxide

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

merry smelt
#

do you still need help with the problem? or maybe you figured it out yourself

pastel oxide
merry smelt
#

for the static one:

import typing

class staticproperty[T]:
    def __init__(self, f: typing.Callable[[], T]) -> None:
        self.f = f
    def __get__(self, _, __) -> T:
        return self.f()

seems to work
the class one im thinking a bit

#

im not sure if its even possible to make a generic classproperty like that pithink

pastel oxide
#

Hmm. This seems very close, though I'm still getting errors.

Mypy: Function is missing a return type annotation [no-untyped-def]
Mypy: Method must have at least one argument. Did you forget the "self" argument? [misc]

For this test code

from typing import Any, Callable, Generic, TypeVar

T = TypeVar('T')


class staticproperty(Generic[T]):
    def __init__(self, f: Callable[[], T]) -> None:
        self.f = f

    def __get__(self, _: Any, __: Any) -> T:
        return self.f()


class Bean:
    @staticproperty
    def get_bean():
        return 'bean'


print(Bean.get_bean)

print(Bean.get_bean + '2')
#

I dont need a classproperty if staticproperty works ๐Ÿ˜

merry smelt
#

well you didnt typehint get_bean, -> str or -> Literal["bean"]

pastel oxide
#

Yeah ๐Ÿคฆ
But this error still stands:

Mypy: Method must have at least one argument. Did you forget the "self" argument? [misc]```
merry smelt
#

hmh

pastel oxide
#

I dont get it with Pylance, only with mypy

merry smelt
#

why does it think its a method, that seems like a bug

pastel oxide
#

Yeah, I think you're right. I'll report it in their issue tracker

merry smelt
#

seems like its actually "correct" in this one, even though it works

#

probally need to do something like this, ugly as hell though

from typing import Callable

class staticproperty[T]:
    def __init__(self, f: Callable[[], T]) -> None:
        self.f = f
    def __get__(self, _, __) -> T:
        return self.f()
    
class classproperty[C, T]:
    def __init__(self, f: Callable[[type[C]], T]) -> None:
        self.f = f
    def __get__(self, _, cls: type[C]) -> T:
        return self.f(cls)

class Q:
    @staticproperty
    @staticmethod
    def f() -> int:
        return 42
    @classproperty
    @classmethod
    def g(cls) -> int:
        return 42
pastel oxide
#

This looks like it yeah. Very cool, thank you ๐Ÿ˜

#

!solved

manic compassBOT
#
Python help channel closed

This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.