#๐Ÿ”’ Questions regarding static typing / typing hints & generic constraints

87 messages ยท Page 1 of 1 (latest)

thorny glacier
#

Hey there. I'm not a python developer, and occasionally I need to code in it a bit. One thing I really need hard is proper compile time checks. So I got pyright (a surprisingly good piece of software) and am using it to check the type errors.

Question 1: dynamic attributes

Apparently in python you might be expected to add some attributes to an existing object on the fly. At least that's what the framework in our project expects.

The problem is, I can't find a way to specify the type:

a.x = 4
a.x = None

This fails with an error in the second line: you cannot assign None to int.

Even doing this doesn't help:

x: Optional[int] = 4
a.x = x
a.x = None

Question 2: generic constraints for multiple types

I hear there's no proper multiple generic constraints in python. For example, I might want to define a trait/contract/type class which has a method, and constrain T to it and a few more "traits". What is the python way of doing it?
It doesn't like this syntax (it doesn't like the '+' in the constraints and I couldn't find a better way)

class IQuack:
    def quack(self):
        pass

class IBark:
    def bark(self):
        pass

def quack_and_bark[T: IQuack + IBark](x: T):
    x.quack()
    x.bark()

Question 3: generic constraints for self-referential generics

Pretty classic stuff:

class IAdd[T]:
    @abstractmethod
    def add(self, y: T) -> T:
        pass

def quack_and_bark[T: IAdd[T]](x: T) -> T:
    return x.add(x)

It says T in the constraint can't be determined because it refers to itself. How do you do it?

Also feel free to share your tips in this area, I'm all ears. Thanks.

lyric thicketBOT
#

@thorny glacier

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.

thorny glacier
#

Questions regarding static typing / typing hints & generic constraints

hollow glen
hollow glen
thorny glacier
hollow glen
#

two different variables, two different types

thorny glacier
#

I don't have access to the original type b/c it comes from a framework

hollow glen
thorny glacier
hollow glen
#

you cant annotate attributes on an instance

thorny glacier
#

:/

#

doesn't sound reassuring ๐Ÿ˜„

thorny glacier
#

maybe i can do an evil thing and inherit that class and then overwrite it but eh

thorny glacier
hollow glen
#

i'm really not sure

thorny glacier
thorny glacier
#

how do python people do all of it

hollow glen
lyric thicketBOT
#

class typing.Protocol(Generic)```
Base class for protocol classes.

Protocol classes are defined like this:

```py
class Proto(Protocol):
    def meth(self) -> int:
        ...
```...
hollow glen
#

you could also make it bound to multiple types

#

instead of T: A + B, do T: (A, B) instead

#

i forgot the term for this

#

param proxy or whatever

thorny glacier
#

huh I thought it's a union

#

why do I need a protocol for that?

#

lemme see

hollow glen
thorny glacier
#

does the protocol part matter here

hollow glen
#

it's cut off

thorny glacier
#

well basically it can't find quack in IBark and bark in IQuack

hollow glen
#

x: IBark | IQuack

thorny glacier
#

I need both methods to be there

#

not either one of them

hollow glen
thorny glacier
#

I need an "intersection", both IBark and IQuack

hollow glen
#

either way, you can make your own by subclassing both class IBarkAndQuack(IBark, IQuack): ...

thorny glacier
thorny glacier
#

unless there's something like auto-implement but I doubt since it's actually "classes" in python

#

sad ๐Ÿ˜ฆ

thorny glacier
# hollow glen can you rephrase?
class IQuack:
    def quack(self):
        pass

class IBark:
    def bark(self):
        pass

class IBarkAndQuack(IBark, IQuack):
    pass

class WeirdAnimal(IQuack, IBark):
    def quack(self):
        print("Quack")

    def bark(self):
        print("Bark")

def quack_and_bark[T: IBarkAndQuack](x: T):
    x.quack()
    x.bark()

quack_and_bark(WeirdAnimal())

Pyright: Argument of type "WeirdAnimal" cannot be assigned to parameter "x" of type "T@quack_and_bark" in function "quack_and_bark"

#

at least Protocols do some useful stuff:

hollow glen
hollow glen
thorny glacier
#

abc?

hollow glen
thorny glacier
#

it's not runtime, it's still compile time

hollow glen
thorny glacier
#

so of course it's the same error and it makes sense to me

thorny glacier
#

I need IBark & IQuack kind of thing

#

do you know C# or rust or haskell?

#

or F#

hollow glen
#

rust too, but just the basics

thorny glacier
#

in C# you'd do Bla<T>(...) where T: IQuack, IBark

hollow glen
#

wait

hollow glen
thorny glacier
#

nope

#

oh, wait

#

unless I make IQuackAndBark a protocol too

#

huh that seems to work

#

That's not great but better than nothing... I guess

#

thanks

#

sadly for self-referential generics or any generic type in constraints it doesn't seem possible:

The specified constrained types must be concrete. An attempt to use a generic type should be flagged as an error by a type checker.

lyric thicketBOT
#
Python help channel closed for inactivity

This help channel has been closed. 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.