#type-hinting
1 messages Β· Page 55 of 1
int | list | tuple seems like a weird combination
what does arg represent in your actual code?
just an example
data ig, in the actual code it's actually int | str | bool | float | list | tuple
not sure what the convention is, but a TypeGuard could work
def is_iterable(x) -> TypeGuard[Iterable]:
try:
iter(x)
return True
except TypeError:
return False
def func(arg: Union[int, list, tuple]):
if is_iterable(arg):
...
else:
...
okayy thx
where should i import typeguard? π
You can get it on earlier versions via typing_extensions on PyPI.
wait a min why does python says cant import TypeGuard from typing_extensions when i m positive it's installed?? (p.s. using py 3.8.8 64-bit)
nvm, i just needa update it breh
from typing import Union
def func(arg: Union[int, float, str, bool]):
...
def foo(arg: Union[int, float, str, bool, list, tuple]):
if type(arg) not in [list, tuple]: # <- NEED HELP!!!
func(arg)
how should i avoid tiz error mypy gives me??
Argument 1 to "func" has incompatible type "Union[int, float, str, bool, List[Any], Tuple[Any, ...]]"; expected "Union[int, float, str, bool]"
mypy doesn't understand that check, use isinstance
okayy lemme try
can you help me with the code? i kinda dunno how to use isinstance π
!d isinstance
isinstance(object, classinfo)```
Return `True` if the *object* argument is an instance of the *classinfo* argument, or of a (direct, indirect, or [virtual](https://docs.python.org/3/glossary.html#term-abstract-base-class)) subclass thereof. If *object* is not an object of the given type, the function always returns `False`. If *classinfo* is a tuple of type objects (or recursively, other such tuples) or a [Union Type](https://docs.python.org/3/library/stdtypes.html#types-union) of multiple types, return `True` if *object* is an instance of any of the types. If *classinfo* is not a type or tuple of types and such tuples, a [`TypeError`](https://docs.python.org/3/library/exceptions.html#TypeError "TypeError") exception is raised.
Changed in version 3.10: *classinfo* can be a [Union Type](https://docs.python.org/3/library/stdtypes.html#types-union).
I've got school, sorry
okay π np
This will actually break at runtime if you supply a subclass of tuple or list
So mypy is correct here
huh?
i dun understand... π
class MyList(list):
pass
The type of this object is not list, so the condition will be False.
wat should i do then?
if isinstance(arg, (list, tuple)): no?
i think so wait a min
nope it doesnt
should be not ...
I'm looking forward to research the subject of type hinting, in the purpose of presenting the subject to a class. Eventually the purpose is to bring myself and the class I'll be presenting to a level of which a high level of understanding regarding type hinting in terms of:
- being familiar with the typing module
- being familiar with python's built-in features
- knowing when to use it and how to use it properly
- getting to know many other modules and features according to the subject
- also proper structural coding according to certain PEP rules
I'd love to know if you guys have any recommendations for any sources, ideas, subjects, modules and so on. And how deep should I be going into this subject? Thanks in advance
I'd start with https://typing.readthedocs.io/en/latest/#type-checkers and follow the links there. The mypy documentation is particularly thorough.
that's great to know, thanks a lot
this source is great, it talks about many things I wanted to discuss and I honestly happened to use many of them
didn't try flake8 but did use black
As for how deep to go, that's up to you. If this is meant to be introductory, I think answering the questions in your above message is going to be a great start, but you can go much deeper into particular subjects if you want to.
In the context of Python type checking, static typing means you use an external tool that you run on your code and that finds type errors. Dynamic typing means checking for bad types when you actually run your code.
right
Sounds like they also want you to do pep8
also proper structural coding according to certain PEP rules
Is a bit vague imho
!pep 484
and this
I just sent a PR to typing to list all the relevant PEPs: https://github.com/python/typing/pull/949/files
awwww π
that's one big catamorphism
Hey hi henlo everyone, would anybody have a couple spare minutes to help me with a specific idea/issue that I encountered, around which I struggle to wrap my head around?
Is there any way to call a function from an annotation on the argument that it annotates?
Let's say I have:
def a_function(str: swapcase):
return str.swapcase()
I do realise the example is kinda stupid, but I hope it conveys what I'm trying to achieve!
You can access a_function.__annotations__ at runtime I guess. Not sure how you'd make this useful though.
Well the discord.py library uses converters, that is where I borrowed the idea from
so like:
@bot.command()
async def mycommand(ctx, member: discord.Member):
await ...
member get's converted to a different object, or more like an object is extracted from another object that is used to pass around
Ah I see, you'd probably want to write a decorator doing that?
It would be hard to make this work with a static type checker though
yea i think i have a working thing for ya back in #π€‘help-banana
class typing.Protocol(Generic)```
Base class for protocol classes. Protocol classes are defined like this:
```py
class Proto(Protocol):
def meth(self) -> int:
...
``` Such classes are primarily used with static type checkers that recognize structural subtyping (static duck-typing), for example...
Yeah, class CanSwapCase(typing.Protocol): ... or similar
For this I don't see the benefit of anything more than str but of course I don't know the context
Is it possible to do something like this
def my_func(arg_a) -> arg_a:
return arg_a
Like is it possible that return annotations can be function arguments?
No, but you can use TypeVar to do something like this
!d typing.TypeVar
class typing.TypeVar```
Type variable.
Usage:
```py
T = TypeVar('T') # Can be anything
A = TypeVar('A', str, bytes) # Must be str or bytes
``` Type variables exist primarily for the benefit of static type checkers. They serve as the parameters for generic types as well as for generic function definitions. See [`Generic`](https://docs.python.org/3/library/typing.html#typing.Generic "typing.Generic") for more information on generic types. Generic functions work as follows...
Interesting, this can help me in something else i am working on thnx
Might be nice to be able to do stuff like:
def foo(v: typing.T < str) -> typing.T: ...
That exists, TypeVar('T', bound=str) - if you mean T must be a str or subclass.
Sure but without having to add an extra line
Yeah it's very awkward having to construct the vars, not really an easy way to get around that.
Tat's why it wasnt working... π Thx man
is there a lower bound type hint?
what is that?
idts
What you do is do TypeVar('T', contravariant=True) to make it contravariant like that.
Then it accepts the subscripted type or any parent types.
Callable return types are contravariant for example.
return types or parameter types?
i think its covariant in the return type and contravariant in the parameters but im not sure
that's right
yeah
its mentioned in pep 483
https://www.python.org/dev/peps/pep-0483/#covariance-and-contravariance
i typically use the mypy docs π https://mypy.readthedocs.io/en/stable/generics.html#variance-of-generic-types
Is it possible to pass in a string in my custom Generic type
without forward referencing it Field[str, "abc"], here "abc" is considered as forward annotation is there a way i can prevent that
Use Annotated maybe
That helps
By they you are referring to me, wasn't given this as a task. I actually volunteered because it seems really interesting. And yes I will also talk about PEP 8 and several others
I dont know if this is the right channel, if not please send the right one.
But how do I run a python file through a variable
ex:
myfilename = "test"
import (myfilename).py
(I heard doing this will run the file i want, im doing this to get the newest version of a file then run it) anyone know how?
I gtg, so please ping me the answer and ill check tomorrow, please and thanks
importlib.import_module("test")?
also yeah, #python-discussion or one of the help channels would have been better suited for this question
Is it possible to typehint a tuple of n string elements where n is taken as a function argument?
def foo(x: Any, n: int) -> Tuple[str, ...]:
return (x, ) * n
No
Why? You can get n as len(tupel)
yall know if its possible to allow multiple types w pydantic? either string or bool
union?
Can you check if a variable exists without getting a KeyError?
entry['author'] will sometime result in a KeyError ,
because when the field is empty, the variable will not be created (from module side).
My workaround right now:
except: entry['author'] = ""```
Sorry if this is the wrong channel for this
dict.get(key, default_val)
will return default_val if the key is not present, otherwise returns the val that corresponds to key
to check if key is in entry:
if key in entry:
print("Found!")
Thank you, that was what I was looking for. π
use Generic[T], not Generic(T)
π€¦ββοΈ thank you
hi
posted this here a couple times, but typing is great
py def foo(bar: Union[Iterable[Union[str, int, float]], Callable[["Context"], Union[Iterable[Union[str, int, float]], Coroutine[Any, Any, Iterable[Union[str, int, float]]]]], Coroutine[Any, Any, Iterable[Union[str, int, float]]]]) -> Callable[["Context"], Coroutine[Any, Any, Iterable[Union[str, int, float]]]]: async def baz(): ... return baz Is Coroutine[Any,Any,X] or Awaitable[X] more correct here? (For typing an async function)
Also, if I want [1,2,3] or ["1", "2", "3"] but not [1, "2", 3], is Iterable[Union[str, int, float]] ok or should I use Union[Iterable[str], Iterable[int], Iterable[float]]?
I would use Awaitable unless otherwise specified.
- It's more concise
- It lets you return a different
Awaitablein the future (that's weird, but it could happen I guess)
Also... do you know about type aliases?
If you want an iterable with consistent items, then you want Union[Iterable[str], Iterable[int], Iterable[float]]
Alright that's what I thought it would probably be
Also @torpid yarrow, I would strongly suggest configuring your editor/CI to reject values: Values = None. It should be values: Optional[Values] = None
Pycharm doesn't have an option for this I'm pretty sure
It just treats that as Optional
Oops, I had made it optional earlier and removed it recently because the parameter should no longer be optional. I'm going to remove the default value anyways
Coroutine has been the standard in my project so far, I actually only recently saw Awaitable. Besides this are there any other reasons?
Wondering if I should use Coroutine to maintain consistency
mypy and pyright both have options for this (strictParameterNoneValue in pyright and --no-implicit-optional in mypy)
Eric made noises recently about flipping the default
And mypy has had an issue for a long time about flipping the default but it tends to move at a more glacial pace
oh, it seems like it makes the type optional sneakily, indeed... that's weird
so it's actually optional but it shows as non-optional??
is this a bug?
yeah that looks like a bug to me
pylance bug to be specific, not pyright
Wouldn't it get the type to display from pyright?
hmmm, reveal_type shows str | None
I opened a bug on pylance
my bets are on Eric closing it with as designed
put reveal_type(x) in the middle of a function
type checkers will recognize that and print the inferred type of x
at least mypy, pyright, and pyanalyze do; I think it's not formally standardized
yeah
so you have to remove it if not type checking?
yes it will throw an error at runtime because the function doesn't exist
there's been some talk about providing a runtime implementation
do you know if guidos gotten anywhere with that jelle?
I don't think anything has happened. Probably it needs someone to actually push it through.
https://www.oreilly.com/library/view/mastering-object-oriented-python/9781789531367/13d1b3d7-12ef-4d21-bd0b-1d45c3ac1ad8.xhtml has a description for a JSON type hint but the there a reason they use Type[None] rather that just None? py JSON = Union[Dict[str, Any], List[Any], int, str, float, bool, Type[None]]
that seems wrong. https://mypy-play.net/?mypy=latest&python=3.10&gist=13436fdc53f2dac02468aad048f9859a
The mypy Playground is a web service that receives a Python program with type hints, runs mypy inside a sandbox, then returns the output.
so it should be JSON = Union[Dict[str, Any], List[Any], int, str, float, bool, None]
you shouldnt really use this cause it just makes thing a pain
if there was an AnyOf class it would be much better over the Union
What's the difference?
AnyOf is theoretically any of the types used to subscript and there shouldnt be any type checking for alternatives in the subscription, however, Union checks all of the items are correctly narrowed
So a bounded Any in a way?
if you use pycharm or maybe pytype Union is what AnyOf should be
not sure I'd like such AnyOf over Any or object
the main proposed use is for language servers/suggestions
JSON = Union[Dict[str, "JSON"], List["JSON"], int, str, float, bool, None]
``` Except mypy still doesn't work with it π
Coroutine is specifically what an async def function returns (or an exact replica), it requires send(), throw(), and close() methods in addition to __await__(). Awaitable on the other hand is just anything that can be awaited, which is more lenient if that's all you require. It's similar to the difference between Iterator and Generator,
Coroutine is what an async def function returns
not the function itself
I meant that yeah.
the python docs use these interchangeably which adds to confusion π
It is a bit confusing, a coroutine function returns a coroutine object, while the function is just the regular types.FunctionType...
Generators are sometimes specified as "generator-iterators", doesn't really work for coroutines though - "coroutine-awaitable"?
Prediction destroyed, it's a bug @oblique urchin π
@overload
def filter_results(
file_results: Dict[str, FileResult], type: Literal["reformatted"]
) -> Dict[str, ReformattedResult]:
...
@overload
def filter_results(
file_results: Dict[str, FileResult], type: Literal["failed"]
) -> Dict[str, FailedResult]:
...
@overload
def filter_results(
file_results: Dict[str, FileResult], type: Literal["nothing-changed"]
) -> Dict[str, NothingChangedResult]:
...
def filter_results(file_results: Dict[str, FileResult], type: str) -> Dict[str, FileResult]:
return {
file: result for file, result in file_results.items() if result.type == type
}
I guess Literal["nothing-changed"] isn't a subtype of str hence why mypy doesn't like the function implementation.
What's the error?
src/diff_shades/analysis.py:149: error: Overloaded function implementation cannot produce return type of signature 1 [misc]
src/diff_shades/analysis.py:149: error: Overloaded function implementation cannot produce return type of signature 2 [misc]
src/diff_shades/analysis.py:149: error: Overloaded function implementation cannot produce return type of signature 3 [misc]
@dataclasses.dataclass(frozen=True, init=False)
class FileResult:
type: ResultTypes
src: str
@dataclasses.dataclass(frozen=True)
class NothingChangedResult(FileResult):
type: Literal["nothing-changed"] = field(default="nothing-changed", init=False)
@dataclasses.dataclass(frozen=True)
class ReformattedResult(FileResult):
type: Literal["reformatted"] = field(default="reformatted", init=False)
dst: str
@dataclasses.dataclass(frozen=True)
class FailedResult(FileResult):
type: Literal["failed"] = field(default="failed", init=False)
error: str
message: str
Oh is this related to mutable containers again?
contra vs co varience or whatever the terms are
Why not ```py
@dataclasses.dataclass(frozen=True)
class NothingChangedResult:
type: Literal["nothing-changed"] = field(default="nothing-changed", init=False)
@dataclasses.dataclass(frozen=True)
class ReformattedResult:
type: Literal["reformatted"] = field(default="reformatted", init=False)
dst: str
@dataclasses.dataclass(frozen=True)
class FailedResult:
type: Literal["failed"] = field(default="failed", init=False)
error: str
message: str
FileResult = Union[NothingChangedResult, ReformattedResult, FailedResult]
and why do you need the type field?
honestly not sure, I've been just treating these dataclasses like dictionaries
@dataclasses.dataclass(frozen=True)
class NothingChangedResult:
src: str
@dataclasses.dataclass(frozen=True)
class ReformattedResult:
src: str
dst: str
@dataclasses.dataclass(frozen=True)
class FailedResult:
src: str
error: str
message: str
FileResult = Union[NothingChangedResult, ReformattedResult, FailedResult]
``` and then use `isinstance`
Technically you're missing the always present src attribute
I think so. Dict[K, Subtype] is not a subtype of Dict[K, Supertype] for the same reason lists aren't.
fixed
Alright, will try that
right, I forgot that I was using the type field during serialization and deserialization to and from JSON
There's probably a better way of handling this.
Well, then the field only makes sense to the part of the code that does serialization. You don't put SQL in the same function as HTTP, right?
so I'd just pick a field during the [de]serialization
although it might be pretty inconvenient
depends on how you're doing it
Yeah that's pretty much the main reason why I did it that way, just treating 'em like dictionaries
I'll look into moving the type field somewhere else if possible.
If anyone needs to write unit tests for type hints you can try out https://pytest-pyright.readthedocs.io/en/latest/
Pytest plugin for typechecking code with Pyright
Still got some kinks that need to be ironed out
Alright. I think I'll end up using Coroutine as it will specifically return an async function, and does not need to be lenient.
you technically should be as lenient as possible when it comes to type hints
its also shorter to use Awaitable[Return] than Coroutine[Any, Any, Return] (although you obviously can use type aliases)
If you do not need what Coroutine provides to keep it functional, using a broader type will keep your api more open to changes
Does anyone know if there is anything I can do about this mypy performance issue
Creating generic classes causes mypy to take 34 minutes to check the code
instead of the previous 8
why two cache actions lol
in a row
Okay there's no need to judge my actions workflows lol
I wrote then ages ago and had no idea what I was doing
nah i just want to make it the best possible
Also it is caching two different things
I love action workflows, but don't worry, you can't make me stressed with these
tldr I had a very stressful moment with workflows earlier
What happened?
tldr mrabarnett/mrab-regex#445
the title should explain it all
Oof
i was also wondering about that, do pyre or others have faster initial startup time than mypy
pyre should be pretty fast as its in not python π
technically, mypy isn't in python either
for normal use, mypy 0.920 will probably be like 2x faster for a run without a cache (https://github.com/python/mypy/pull/10922)
will mypy 0.920 or The Winds of Winter appear first though
at what point does mypy take longer than pre-release-automation black?
to be fair mypy does wayy more testing than we do
black's longest gap was 10 months, mypy is only at 5
Feels way longer than that .. not sure what to make of that
I think the June releases already didn't include everything that was on master at the time
Yeah and it appears 0.920 will be similar
yes it was branched months ago
is it possible to type hint like tiz?
class MyClass:
def __init__(self, arg: MyClass): ...
You'd need topy from __future__ import annotations
n then?
__future__ is basically features that have already been coded, just not officially added yet (for one reason or another)
Support for this has already been coded, just not implemented into an official Python release. You can "implement" it in your project by doing the import
oh okay
@solid light well than is vscode (pylance to be specific) giving me an error normal?
ig so...
Well, what's the error?
py 3.8.8, dunno if tat's the prob, the error: NameError: name 'MyClass' is not defined
Show ur full code
Well that doesn't have the import so it can't be everything
never mind i solved it, careless mistake π thx a lot
@pastel egret does mypy work with __future__ annotations then?
It should accept it yes.
beartype.roar.BeartypeDecorWrappeeException: <class '__main__.MyClass'> unsupported, as classes currently unsupported by @beartype.?
@beartype
class MyClass:
def __init__(self, arg: MyClass): ...
Beartype currently can't annotate classes themselves, you need to use it individually on all the functions.
Can confirm, in my case pyright takes about 12 seconds to type check the codebase while mypy takes around 8 minutes, like 40x slower lol
I've also had to disable multiple features from being generated when using mypy because they either cause nypy to take an unreasonable amount of time to type check or to straight up crash
breh i found the error
class MyClass:
@beartype
def __init__(self, arg: Union[str, MyClass]): ...
beartype will give tiz loooooong error but i think the main error is tiz:
beartype.roar.BeartypeDecorHintPep563Exception: @beartyped MyClass.__init__() parameter "arg" PEP 563-postponed type hint 'Union[str, MyClass]' syntactically invalid (i.e., "name 'MyClass' is not defined") under:
@pastel egret sry for the ping
Then why did you ping me?
lmao
And that is correct since it isn't yet defined when you execute the decorator.
You need to change it to arg: Union[str, 'MyClass']
If I have a generic object which also inherits from a base
class Attribute(Generic[T_Typehint], Object):
...
Like that?
Other way around
The Generic should be last
(I'm not fully sure if it matters but I believe it does)
it doesnt
Ah okay
is there a way to say to a class that it must have properties with certain instances of classes? something like
class Foo:
pass
class Bar:
pass
class NotAllowed:
pass
class Test:
foo = Foo()
bar = Bar()
not_allowed = NotAllowed() # make this class accept only properties that are instances of Foo and Bar
you cannot
it is impossible in python
classes have other properties, such as __doc__ and __class__, with certain types
you cannot say that all properties have some type, because it isnt true
Well you can't type hint it, but you can override __setattr__, and error out if the value isn't one of those.
you can typehint some properties:
class Foo:
pass
class Bar:
pass
class NotAllowed:
pass
Foo_or_Bar = Foo | Bar # Union[Foo, Bar]
class Test:
foo: Foo_or_Bar = Foo()
bar: Foo_or_Bar = Bar()
not_allowed: Foo_or_Bar = NotAllowed() # there should be an error
test = Test()
test.foo = 1 # error
test.foo = Bar() # ok
also, if it is class variables, you can use metaclass and check types on class creation
(sorry for my language)
i see
https://mystb.in/AlphaMainlandBeta.python
is there any way to avoid the error at the bottom?
the first parameter isn't being concatenated because the function takes self as a parameter, which makes it appear as a MethodOfClass
having to rely on the parameter name to check if it's a method of a class isn't great, but i'm not sure how else to do it
What you probably need to do is make alru_cache a descriptor. The reason you can't find another way to check is that functions defined in and out of a class is exactly the same, the difference is when accessing the attribute.
I'll try that thanks
another thing that makes this challenging is that __get__ isn't called when the object is accessed globally, so I'm not sure how to handle parameters there, because my current logic is based on concatenating the instance to the parameters if it was accessed by the class itself
e.g. A.in_class(a, 1, '') in my example doesn't error
Couldnβt you define __call__()?
i'm doing that, but the same issue here happens
I mean if that's called, it's a regular function. If __get__ is called, it is accessed from a class or instance.
thanks, though i'm a bit confused how to implement this
https://mystb.in/EffortNextelPosters.python
what do decorators return?
def timed(ndigits: int= 5):
def real_timed(func):
def wrap(*args, **kwargs):
time_start = time.time()
return_val = func(*args, **kwargs)
time_end = time.time()
print(f"[*] {func.__name__} took: { round(time_end - time_start, ndigits) }")
return return_val
return wrap
return real_timed
A Callable
-> callable
You'll want a TypeVar or ParamSpec so the original function's signature is preserved.
Fortunately it's a signature preserving decorator so you don't need ParamSpec
Because mypy doesn't support ParamSpec yet q.q
wait, mypy infers *args, **kwargs for decorators?
i had no idea
oh, it doesn't, they use cast() in the example
also --strict doesnt let you get away with those untyped varargs
Mypy just complained with this Argument 1 to "open" has incompatible type; expected "Union[Union[str, bytes, PathLike[str], PathLike[bytes]], int]" [arg-type]
I get the string/path ones but why is int a valid type for open 
If you have a file descriptor, you can use that to re-open that same handle.
mypy bug?
I suppose... Although why would you do that?
just to check mypy behavior xD
it isnt a very useful case
also pylint gives me interesting warning on third line:
pylint: warning W0238 - Unused private member 'X1.__m(self)' (unused-private-member)
π€
Yeah mypy should read that as _X1__m
how would i declare Generic[T] so that it takes undefined amount of types, mypy is just expects 1 type argument, but n given
The Steering Council has basically accepted this, there's just one edge case to sort out.
ohh
https://github.com/python/mypy/issues/9910#issuecomment-759925755 lol Guido being slightly salty here?
Quick question, is there a way to typehint a weakref set?
For the sake of autocompletion I could just use x: t.Set[XYZ] = weakref.WeakSet(), but that's a wrong typehint of course, especially because the WeakSet doesn't inherit from set
you should be able to use weakref.ref as the generic argument if I understood correctly
>>> x: WeakSet[Something] = WeakSet()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'type' object is not subscriptable
The problem is the type is unusable in a hint
Some quick searching has led me to a stackoverflow thread that shows a need to inherit from typing.Generic for this hint to work, but how would you do that for an already existing class?
you need put it in quotes
or update your version of python to 3.9+
x: "WeakSet[Something]" = WeakSet()
or use future.annotations
Such a simple fix, that's done it, thanks π
Haha π
Pyright chad: 
- fixes bugs in a few hours, lives outside our notion of timezones
- recursive type aliases
- fast
Mypy: - lots of open issues
- how did you abbreviate
analyzeagain?..
||/hj||
It's got recursive types?
TIL
Thing is I need the zope and Django and sqlalchemy plugins
Yep, e.g. this is a very simple linked list
Linked = Optional[tuple[T, "Linked[T]"]]
Dang
Yeah, I don't think pyright will get that any time soon
Unless I figure out how to read its code π
And hack it in
typehints are so weird because they can be so easily abused lol
an example they provide:
@bot.command()
async def clean(ctx, *, content: commands.clean_content(use_nicknames=False)):
await ctx.send(content)
that's not really a typehint but a plain annotation
PSA: callback protocols (Protocol subclass with a dunder call) require you to also use the same name, not just the same type (at least when checked by pyright)
i just spent multiple hours before i realised the reason pyright was throwing a error was not because of the type, but because of the argument name.
annotations are defined in pep 3107 and let you attach arbitrary metadata to functions/names (depending on the scope) while typehints are defined by pep 484 (and others) and use the annotation syntax
ahhh
that makes me wonder
is there a way to duplicate them?
use both the annotation for arbitrary metadata, and a typehint?
typing.Annotated was recently added for that
ah, okay
Ahh, yeah makes sense if they can be used with keywords.
protocol?
Protocols allow a more powerful way of defining types that typecheckers can check against. Generally, if you just want to typehint "any class that has a .open method with these arguments" you would make a protocol.
Callback Protocols are done by defining a __call__ in the Protocol, which makes them a Callable. its a more powerfull way to typehint a callable than typing.Callable
i think they're called callback protocols because thats their main usecase.
interesting, is there a way to check a class implements said protocol?
yes, you can decorate the protocol with @runtime_checkable to make it work in issubclass
!e ```py
from typing import Protocol, runtime_checkable
@runtime_checkable
class Openable(Protocol):
def open(self, arg: str) -> str:
...
class MyOpenable:
def open(self, arg: str) -> str:
return "yay"
print(issubclass(MyOpenable, Openable))
@dim trail :white_check_mark: Your eval job has completed with return code 0.
True
but the more common usecase is for a static typechecker such as mypy or pyright
though afaik the door is still open for other applications of annotations
but I've not actually seen one as of yet
I'd say that what FastAPI is doing can be somewhat categorized there
with typehinting being a very nice tool in a lot of cases, im not sure i would actually want many other things using the annotations, as that would lock me out of using type-hints
that's what Annotated aimed to solve, but last time I checked the common runtime users of annotations didn't support it
pydantic supports it
Annotated could have been made a lot more powerful by the kwarg getitem pep that was denied
so i have
T = TypeVar("T")
O = TypeVar("O")
class AttributeMeta(type):
def __getitem__(self, params: Tuple[List[T], dict]) -> T:
# Implementation skipped
class Attribute(Generic[T, O], metaclass=AttributeMeta):
pass
val: Attribute[[int], {"name":"value"}]
This works but type checkers aren't happy with it, so is there a way to like indicate it to type checkers like mypy that this is valid?
No, that's too dynamic for mypy. It will likely work with pyanalyze though (depending on exactly what your implementation does).
it convers the list of T into a union of them and the dict is converted to a named tuple and then it returns typing.Annotated with the union and the named tuple
Hey my dudes
Question about singletons
class Singleton(type):
def __call__(singleton: Singleton, *positional: Any, **encyclopedic: Any) -> T_Singleton:
...
With a singleton, the 'self' arg in the call method is an instance of singleton, right?
And, its a class. What comes out of the call method is an instance of that
How do I hint that properly?
oh there's one of these in h11
H11?
they do this:
from typing import TypeVar, Type, Tuple, Any, Dict
_T_Sentinel = TypeVar("_T_Sentinel", bound="Sentinel")
class Sentinel(type):
def __new__(
cls: Type[_T_Sentinel],
name: str,
bases: Tuple[type, ...],
namespace: Dict[str, Any],
**kwds: Any
) -> _T_Sentinel:
assert bases == (Sentinel, )
v = super().__new__(cls, name, bases, namespace, **kwds)
v.__class__ = v # type: ignore
return v
def __repr__(self) -> str:
return self.__name__
class CLIENT(Sentinel, metaclass=Sentinel):
pass
I'm not sure if __call__ is the right method - isn't it __new__ on type?
h11 has a special requirement that type(CLIENT) is CLIENT
I figured it'd have something to do with binding a typevar. I thought that that just set a lower threshold for the inheritance chain. So it would, for example, prevent object from matching
so you don't need quite that much magic
tbh I'd probably just use an enum on a fresh project
I couldn't get a quick explanation on what 'bound' does could I? I've searched for one in the past but I've never found a direct answer
Binding as in the bound keyword?
Yeah
Bound adds a type restriction, otherwise anything can be passed
So if you do bound='Sentinel' then only an instance of sentinel or an instance of a subclass of sentinel can be passed
So with this, _T_Sentinel represents the instance, while Type[_T_Sentinel] represents it's class. And _T_Sentinel is bound to the class of the class π
Metaclasses are always hard to follow, but that doesn't seem right to me
Yeah that's right, it's so that the methods propagate for subclasses
_T_Sentinel is the class, Type[_T_Sentinel] is the metaclass
you wrote the same thing twice?
I thought I was hallucinating XD
it's a bit unusual to make something both a base and a metaclass for clients
if you're going to do that then you may as well just provide a stub base class, with the metaclass in question, and then clients just inherit from that
and don't have to repeat themselves
Either that or don't combine the functionality
I'm not totally sure I understood the original problem.
I'm just wondering what the right way to hint the return of the meta's __call__ method is
so Singleton is a meta class?
yeah
it would need to be generic, I'd assume
I don't really understand the problem but shouldn't it be _T_Sentinel?
I highly recommend avoiding this problem by avoiding singletons, which are an anti-pattern anyway π
btw, generic metaclasses are not supported, unfortunately, so making this work in the ideal may not be possible
at least not in mypy, not sure if you're planning to use a different type checker
from typing import Sequence, Type, TypeVar
T = TypeVar("T", bound=Type)
def my_filter(items: Sequence[object], cls: T) -> Sequence[T]:
return [v for v in items if isinstance(v, cls)]
some_stuff = [1, "a", 2.2, (1, 2)]
integers = my_filter(some_stuff, int)
reveal_type(integers)
test.py:6: error: List comprehension has incompatible type List[object]; expected List[T] [misc]
test.py:10: note: Revealed type is "typing.Sequence[Overload(def (x: Union[builtins.str, builtins.bytes, typing.SupportsInt, typing_extensions.SupportsIndex, builtins._SupportsTrunc] =) -> builtins.int*, def (x: Union[builtins.str, builtins.bytes], base: builtins.int) -> builtins.int*)]"
Did I misuse TypeVar here? or is mypy just not smart enough to use that isinstance to do type narrowing?
!d typing.TypeVar
class typing.TypeVar```
Type variable.
Usage:
```py
T = TypeVar('T') # Can be anything
A = TypeVar('A', str, bytes) # Must be str or bytes
``` Type variables exist primarily for the benefit of static type checkers. They serve as the parameters for generic types as well as for generic function definitions. See [`Generic`](https://docs.python.org/3/library/typing.html#typing.Generic "typing.Generic") for more information on generic types. Generic functions work as follows...
Alright, cool, I totally misunderstood what bound=... does.
You used it correctly for cls, if you're wanting to pass a subclass of type/Type which you are.
But you can't then do the reverse of Type to get the sequence subscript.
What you want is for T to represent the instances, not the type itself:
T = TypeVar("T")
def my_filter(items: Sequence[object], cls: Type[T]) -> Sequence[T]:
return [v for v in items if isinstance(v, cls)]
Ah, that makes way more sense.
and yes I did realize that after re-re-reading the typevar docs
Thank you!
No problem.
You might want to make items just Iterable[object], since that's all you require.
yeah I would but that was just a toy example from having simplified a bit more complicated bit of code :)
Ah sure!
def aaa() -> callable:
...
bbb = aaa()
reveal_type(bbb)
This shows Any -> bool on pyright...
Interesting
Huh, that should fail
That's a really confusing behaviour, that should give a warning on hover instead of literally the type of callable
I'll report this is l when I get home
Or well, anyone can report
It does fail in the bbb definition site. But the definition site could be in library code.
huh
class X(Generic[A, B]):
_dict: dict[A, B]
_pair: X[B, A]
def method(self) -> None:
pair = self._pair
reveal_type(self) # X[A, B]
reveal_type(self._dict) # dict[A, B]
reveal_type(pair) # X[B, A]
reveal_type(pair._dict) # dict[A, B] WTF???
```pyright is shit
mypy is better
WTF???
That's all working as expected, is the issue that there's no initializer?
You basically have a recursive type there with self._pair π€·ββοΈ
it should be dict[B, A]
mypy works fine in this case
What you have to the left is that a representation or exactly what it outputted?
comments - pyright output
Pyright shows dict[A, B] because A and B are scoped to the X context not the child context
first three cases are ok, fourth is not ok
Because I would bet that A, B is referring to self._pair's A and B generics, (which are defined as B and A of the "parent" X).
^
What happens if you make the types concrete?
pyright actually shows: dict[A@X, B@X]
As in, do it on an instance where the generics have been filled in.
this fixes the issue:
def method(self: X[A, B]) -> None:
There is no issue, pyright shows dict[A, B] because those are the types in that context
In that case it could be a bug - but I am still not convinced
I am on my phone but can you show this code? ```python
instance: X[int, str]
reveal_type(instance)
reveal_type(instance._dict)
reveal_type(instance._pair)
reveal_type(instance._pair._dict)
Show what PyRight outputs
outside the method all works fine
class X(Generic[A, B]):
_dict: dict[A, B]
_pair: X[B, A]
instance = X[int, str]() # without initialisation pyright complains
reveal_type(instance) # X[int, str]
reveal_type(instance._dict) # dict[int, str]
reveal_type(instance._pair) # X[str, int]
reveal_type(instance._pair._dict) # dict[str, int]
it works outside the method because when you are inside the method, the typevars A and B are scoped to the parent context
Yes, that's because what you're shown is the name of the type variables.
patch._dict's variables are A, B which come from patch - who's variables are A, B **defined as X's B, A.
I assume this is your argument though? That you want the behaviour of MyPy.
yea, mypy works fine without explicit typing self in method
The actual resolved types are correct, it's just the representation of them thats different
But- no you don't need that, what you're seeing is to-be-expected and makes sense from the type checkers perspective as I've explained above.
no, it complains in some places, where is no error
What are the error messages?
That could be a bug then, open an issue and it'll be fixed in a few days - compared to MyPy hehe π
Okay, nevermind that does look like an actual bug
more like a few hours lol
Yeah but I didn't want their mind to explode hearing that π
For the record I think MyPy is good but I am just giving it shit because Denball here is super confident about how shit Pyright is
is the pyright dev some a full time MS employee who only works on pyright?
I think so
makes sense
yeah it's insane how fast he fixes bugs
oh, thank you!
from __future__ import annotations
from typing import TypeVar, Generic
from typing_extensions import (
Self,
TypeVarTuple,
Unpack,
)
T = TypeVar('T')
TT = TypeVarTuple('TT')
# this works:
def f(*args: Unpack[TT]) -> tuple[Unpack[TT]]:
return args
reveal_type(f(1, '', [])) # -> tuple[int, str, list]
reveal_type(f()) # -> tuple[()]
class X(Generic[T]): pass
# this is not working:
# vvvvvvvvvvvvv what to write here?
def g(*args: Unpack[X[TT]]) -> tuple[Unpack[TT]]:
# i tried:
# Unpack[X[TT]]
# X[Unpack[TT]]
# X[TT]
# Unpack[X[Unpack[TT]]]
return tuple[Unpack[TT]]()
# i want:
reveal_type(g(X[int](), X[str](), X[list]())) # -> tuple[int, str, list]
this is related question
maybe something like this?```py
XTT = tuple(X[T] for T in TT)
def g(*args: Unpack[XTT]) -> tuple[Unpack[TT]]: ...
@tranquil turtle tuple[T, ...] is a variadic but homogeneous tuple
i know
i want variadic tuple with all items wrapped with X[...]
example: g(X[int], X[str], X[list]) -> tuple[int, str, list]
i want to do this generic
before i uses this:
def g(*args: X[Any]) -> tuple[Any, ...]:
but this is bad for obvious reasons

can you give an example?
def g(*args: A|B|C) -> tuple[A|B|C, ...]:
return tuple(args)
unless i misunderstand your intentions
i'd argue that perhaps this is a confusing interface anyway and maybe should be written another way
def g(*args: X[T]) -> tuple[Union[all T which appears in args], ...]:
did you use from __future__ import annotations?
also not all types are callable like that
(i did not)
what is X? this means that g accepts several arguments of type X[T], not that args is an X (because obviously it's not, it's always a tuple)
it still raises the same error
def to_backup_data(input: Dict[Literal["com", "ext", "filename", "fsize", "h"], Any]) -> Post:
Mypy thinks that key is a string, thats why the error is raised
e.g. this works:
def foo(post: Post) -> None:
key: Literal['w'] = 'w'
print(post[key])
but this doesn't:
def foo(post: Post) -> None:
key: str = 'w'
print(post[key])
happy to help, you can just ignore the error in this context as you know that you're right
X is some generic class with one argument (for example: wrapper around one value)
i want function g, which gets values from all X's and return tuple of this values
i see, i think the problem is that inferred TypeVars can't be Unions
at least, i couldn't get them to work that way
That's not possible in Python unfortunately
this is literally me every day
there's no reason it shouldn't be possible though right?
https://mypy-play.net/?mypy=latest&python=3.10&flags=strict&gist=02b581a4d8df54dcbe7d2d43108c9b2a
from typing import Generic, TypeVar
T = TypeVar('T')
class X(Generic[T]):
value: T
def __init__(self, value: T):
self.value = value
def f(*args: X[T]) -> tuple[T, ...]:
return tuple(arg.value for arg in args)
args = f(X(1), X('hi'))
reveal_type(args)
main.py:13: error: Cannot infer type argument 1 of "f"
main.py:15: note: Revealed type is "builtins.tuple[Any]"
Found 1 error in 1 file (checked 1 source file)
The mypy Playground is a web service that receives a Python program with type hints, runs mypy inside a sandbox, then returns the output.
i want this to infer that T is int | str
reveal_type((X(1), X('hi')))
main.py:13: note: Revealed type is "Tuple[__main__.X[builtins.int*], __main__.X[builtins.str*]]"
I actually thought you wanted it to infer tuple[int, str], hence the typescript reference
so it's mypy's fault I guess?
well that'd be even better
oh wait
so pyright seems to do the right thing
replace TS with rust and that's half of the server /hj
definitely dawn and aboo
https://mypy-play.net/?mypy=latest&python=3.10&gist=a1ef80b4149e3af39ba4c522711e73fb
this works with mypy
from typing import Generic, TypeVar, Union
T = TypeVar('T')
class X(Generic[T]):
value: T
def __init__(self, value: T):
self.value = value
def f(*args: X[T]) -> tuple[T, ...]:
return tuple(arg.value for arg in args)
arg1: X[Union[int, str]] = X(42)
arg2: X[Union[int, str]] = X("hi")
args = f(arg1, arg2)
reveal_type(args)
yeah, but ew
might as well do f(cast(X[int | str], X(1)), cast(X[int | str], X("hi")))
lmao
Speaking of cursed mypy errors:
https://mypy-play.net/?mypy=latest&python=3.10&gist=2e1ccfb574d2209172dcc881d05e5e8f
from typing import Mapping
def f(x: Mapping[str, object]) -> int:
d = {
"foo": 3.14,
**x,
}
return len(d)
``` ```
main.py:7: error: Argument 1 to "update" of "dict" has incompatible type "Mapping[str, object]"; expected "Mapping[str, float]"
Firstly, this shouldn't be an error. It should do what pyright does -- infer d's type as dict[str, Unknown]
Secondly, I'm not calling the update method for goodness sake!
I got really confused by this today
And if you enable the strictDictionaryInference option in pyright, d is inferred as dict[str, object | float]
always has been
in a serious way
I made an issue https://github.com/python/mypy/issues/11604
why are type checkers so buggy and weird? π€
hey, what is this shiny new thing
Everyone is making their own hype checker
time to make my own
#hype-tinting
lmaoo
is there a non-deprecated way to write
typing.Callable[..., typing.Any]
``` ?
Is that deprecated?
I tend to use Protocol if I need a fancy callable
class SupportsCall(typing.Protocol):
def __call__(self, *args: object, **kwargs: object) -> typing.Any: ...
I didn't think so, @vagrant dagger , but beartype was complaining about it.. I got past it by dropping the annotation
that's a nice way.. the Callable ones are kind of unweildy
Can beartype check callable return types like that?
There's no way of knowing what a Callable will return until you call it
hmm ...
Isn't that just a plain typing.Callable/collections.abc.Callable ?
Huh til typing.Callable is deprecated
!e
import typing
import collections.abc
collections.abc.Callable[[], 2]
print("why is it that collections.abc.Callable[[], 2] works")
typing.Callable[[], 2]
print("but typing.Callable[[], 2] fails?")
@grave fjord :x: Your eval job has completed with return code 1.
001 | why is it that collections.abc.Callable[[], 2] works
002 | Traceback (most recent call last):
003 | File "<string>", line 6, in <module>
004 | File "/usr/local/lib/python3.10/typing.py", line 1182, in __getitem__
005 | return self.__getitem_inner__(params)
006 | File "/usr/local/lib/python3.10/typing.py", line 309, in inner
007 | return func(*args, **kwds)
008 | File "/usr/local/lib/python3.10/typing.py", line 1188, in __getitem_inner__
009 | result = _type_check(result, msg)
010 | File "/usr/local/lib/python3.10/typing.py", line 173, in _type_check
011 | raise TypeError(f"{msg} Got {arg!r:.100}.")
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/uhanenolus.txt?noredirect
I don't think any of the new generics validate their args
!e list[0]
@void panther :warning: Your eval job has completed with return code 0.
[No output]
!e
import collections.abc
collections.abc.Callable[2, 2]
@grave fjord :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 2, in <module>
003 | File "/usr/local/lib/python3.10/_collections_abc.py", line 436, in __new__
004 | raise TypeError(f"Expected a list of types, an ellipsis, "
005 | TypeError: Expected a list of types, an ellipsis, ParamSpec, or Concatenate. Got 2
there's a little bit of validation done on Callable it seems
what is Protocols?
what do you mean by nested return?
a little bit like an interface - but for duck typing
create a mypy play?
The mypy Playground is a web service that receives a Python program with type hints, runs mypy inside a sandbox, then returns the output.
what's the difference between an abc then? /srs
and collections.abc.Callable[[0], 0] works even though it says it expected a list of types
some of the collections.abc are in fact treated as a Protocol by type checkers
Why did they decide to draw the line there but don't validate further like the typing version
so what exactly does the protocol mean, and how is it used?
generic type parameters: https://mypy.readthedocs.io/en/stable/generics.html#generics
although there's a bunch of other places where [] means something slightly different eg v: Final[int] = 2
do you want to return [] instead?
eg https://mypy-play.net/?mypy=latest&python=3.10&gist=fe862005760f3355ca45176de54bf596&flags=strict
The mypy Playground is a web service that receives a Python program with type hints, runs mypy inside a sandbox, then returns the output.
!e
contiguousVals = []
min(contiguousVals) + max(contiguousVals)
but then you get this at runtime
@grave fjord :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 2, in <module>
003 | ValueError: min() arg is an empty sequence
is it possible to not have any contiguousVals at runtime?
ah right but mypy doesn't know that
so you need to prove you handle the case or use an assert contiguousVals is not None or something to flatten the Optional
so collections.abc.Callable is preferred over typing.Callable ?
be careful though because python -O0 will disable them
https://github.com/asottile/reorder_python_imports#rewriting-pep-585-typing-imports will automatically upgrade them for you
do people ever run with that?
oh, cool
I just did to get around a buggy assert, but I don't think it's very often done (I've heard people use it "for production")
what is the 0 for?
__debug__```
This constant is true if Python was not started with an [`-O`](https://docs.python.org/3/using/cmdline.html#cmdoption-O) option. See also the [`assert`](https://docs.python.org/3/reference/simple_stmts.html#assert) statement.
my bad, it's just -O
-OO is double optimized, if that's what you meant π
pretty much everyone always runs python in __debug__ mode :p
At work I once tried to run python in "optimized" mode (which strips docstrings) and everything failed to import because some library unconditionally accessed __doc__ at runtime
you can run it in the first layer, but not the second then
python -O will work but python -OO strips the docstrings
what library does that
a poorly coded one
also i wonder what the benefit of -O ever is or was
some data sciency thing, it was a long time ago
let me see if I can reproduce it now
well, since __debug__ and assert statements, it was probably internal validation of stuff, or long debugging statements, or breakpoints, or other things.
param_rule.__doc__ = func.__doc__.replace('xxx', xxx).replace('yyy', yyy)
this one
and pyspark ``` File "/home/jelle/ans/venv/lib/python3.6/site-packages/pyspark/conf.py", line 72, in <module>
doc = re.sub(r"(\W|^)uU", r'\1\2', doc)
oh that
i've seen that, pymongo i think does it too
or motor does it using pymongo doc strings
actually i wonder how does functools.wraps handle that?
it doesn't do string mangling
can you detect the -O level at runtime? it would be a trivial fix to guard that behind a check
yeah something in sys
what's the reason for the operations?
adding docstrings to dynamically generated classes and functions
skimage fails too ``` File "/home/jelle/ans/venv/lib/python3.6/site-packages/skimage/measure/_regionprops.py", line 634, in _parse_docs
doc, flags=re.DOTALL)
!d sys.flags
sys.flags```
The [named tuple](https://docs.python.org/3/glossary.html#term-named-tuple) *flags* exposes the status of command line flags. The attributes are read only...
that and for pyspark, something with unicode decoding for Python 3 only
What's that useful for?
code introspection iirc
tools that frequently are used in an interactive context like pyspark, so you get nice help() output. also tools like sphinx don't rely on static analysis, they actually import your module which causes the whole thing to be exec'ed
code(argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize, flags, codestring, constants, names, varnames, filename, name, firstlineno, linetable, freevars=(), cellvars=(), /)
can i ignore type errors of a type alias? (just to annotate the funcion)
Context = discord.ext.commands.context.Context
i dont think the library has stubs
it does have stubs
either the library is typed if you use v2 or there are types-discord or something that someone made
!pypi discord.py-stubs
How do you use NamedTuple in type hinting? is in like NamedTuple[str, str] or do I need to specify the name of my particular named Tuple
class typing.NamedTuple```
Typed version of [`collections.namedtuple()`](https://docs.python.org/3/library/collections.html#collections.namedtuple "collections.namedtuple").
Usage:
```py
class Employee(NamedTuple):
name: str
id: int
``` This is equivalent to:
```py
Employee = collections.namedtuple('Employee', ['name', 'id'])
```...
shows how to use it
Hmm, okay, thanks
Oh, I can also just use the name of my named tuple as long as I define it in scope, that's much cleaner
?
Oh well I made a named tuple like so, start_finish_tuple = namedtuple('start_finish_tuple', ['start', 'finish']) and I just wanted to add a type annotation for that particular named tuple, not any generic NamedTuple
but I can write def some_function() -> start_finish_tuple: as long as start_finish_tuple is defined in scope
if you're using typing, why use the untyped namedtuple? @open hawk
i think they are changing that
Ah I see
I don't think there's a way to require a namedtuple without naming a specific one, that'd be strange
Yeah that makes sense
Tuple[str, str] is also compatible with your namedtuple as well
I didn't read far enough, you can add type annotations in your namedTuple definition like so
start_finish_tuple = namedtuple('start_finish_tuple', [('start',str), ('finish',str)])
not the standard collections version
idk if you can even still use that old syntax anymore on the typing version
oh you can
Oh, my IDE didn't like that, the only change need is
start_finish_tuple = NamedTuple('start_finish_tuple', [('start',str), ('finish',str)])
In the long run this is likely to be changed to a timestamp, but you know, YAGNI (yet)
i'm curious though, why use a namedtuple instead of simply a dataclass with frozen=true
lol because I'm just familiar with namedtuples and unfamiliar with dataclasses.
No better reason than that
tbh I'd just get used to dataclasses then π
I hear they're useful, and I probably will soon, I'm just trying to get a minimum-viable-product for a colleague
fair enough
I also jus discovered that my tuple is actually holding pandas.Timestamp values, thanks typing π
I had forgotten that the weren't just a date string
but why not the class version?
class StartFinish(NamedTuple):
start: str
finish: str
I thought those were equivalent?
lol I just liked the one-liner definition, but after adding typing it's a bit verbose, so I think I actually like the class version more
at that point you really may as well use a dataclass lol
almost identical
the main thing is that the dataclass gives you a lot more control over certain things, if you'r einterested, and the dataclass will not have numeric access, and *
in most cases when I have something like this, I don't want people doing things like start_finish[1]
or *start_finish
Is is as simple as an annotation?
wdym?
Data classes, I wanted to figure out to use them. It really seems like it is as easy as an annotation
you mean a decorator?
yes
Right, lol, it's called an annotation in Java
I think it's a bit different in Python
in Python it's just syntax sugar for a function call
yeah, just
@dataclass
class StartFinish:
start: str
finish: str
@open hawk
by default you'd be able to modify stuff
s = StartFinish("hi", "bye"); s.start = "hello" would be legal
if you pass frozen=True to the decorator then it would be more like a named tuple in this regard
Awesome
pycharm evals the string in Literal? How to prevent it though
i'm pretty sure that's a pycharm bug
I've update it to 2021.2.3 (The newest I believe) but still appears which is kinda... annoying
that's a shame. i haven't used pycharm much at all since i got neovim lsp and dap set up and running. file a bug report?
:incoming_envelope: :ok_hand: applied mute to @rustic gull until <t:1637828340:f> (9 minutes and 59 seconds) (reason: duplicates rule: sent 4 duplicated messages in 10s).
ah that bug was reported already. And it's "claimed" to be fixed
can someone tell about the class methods that have __ i know they are dunder methods but i wanted to know if we can create our own ad does it follow pep8
If you're talking about __dunder__ methods, they're all described here: https://docs.python.org/3/reference/datamodel.html
aside from that, they're normal methods, and you can create your own __foo__ or __bar__ method.
this is also not the right channel, you should see #βο½how-to-get-help
like that i know about the dunder methods i wanted to know if its allowed in pep8 to create our own __foo or __bar__
Generally, your methods should be in snake_case: https://www.python.org/dev/peps/pep-0008/#method-names-and-instance-variables
Why do you want to create a custom 'dunder method'?
i think i should rephrase what i wanted to ask
i want to know if pep8 allows creating methods with starting double underscore
starting double underscore with no ending underscore has a special meaning
but aside from that, it tells that methods should be in snake_case, so I guess no
PEP8 is just a convention. You don't have to follow it
yes i didnt undertsand it properly in the docs, is it possible if you tell me?
The answer is no, the language docs themselves prohibit use of dunders in any ways not described by it - any future version might change behaviour without any notice.
https://docs.python.org/3/reference/lexical_analysis.html#reserved-classes-of-identifiers
yea true, but best to not get nagged by people
ah okay thank you
oh I remember the __async_init__ hack from asyncpg...
For __names, in classes those are changed to _ClassName_name. That way if you have superclasses and subclasses, both can use an attribute name and it won't interfere with each other.
!e
names that start with __ are 'mangled' so that they don't conflict with potential subclasses
class A:
def __init__(self, name):
self.__name = name
def introduce(self):
print("I am", self.__name)
a = A("foo")
a.introduce()
print(a._A__name)
print(hasattr(a, "__name"))
@trim tangle :white_check_mark: Your eval job has completed with return code 0.
001 | I am foo
002 | foo
003 | False
anyway, this is really off topic for this channel
why does mypy gimme tiz error
alias = int | float | str | bool
Unsupported left operand type for | ("types.Union")
What's your Python version and mypy version?
py 3.10.0
mypy 0.91.0
brehh
It works on the latest GitHub version
This should be fixed in 0.920
https://github.com/python/mypy/issues/11158
21 Sep
I will be releasing mypy 0.920 soon
well...
π
u mean it's not released yet?
bruh
so wat's wrong @trim tangle ? it's just a mypy bug?
bruh
There was some activity yesterday!
how should i fix tiz mypy error? Cannot find implementation or library stub for module named "beartype"
It has a py.typed file, so it should be fine if you're running mypy in the same venv as the beartype
Running mypy with pre-commit?
just wanna confirm, in py3.10 it is recommended to do tuple[int] instead of Tuple[int] right?
yeah
unless you support less than 310 π
yeah like 3.9 :P
the joke was that that feature was added in 3.9
okayy thx
What would be the best way of type hinting a dict without having to import typing?
dict
self.card_deck = {
"A": 1,
"2": 2,
"3": 3,
"4": 4,
"5": 5,
"6": 6,
"7": 7,
"8": 8,
"9": 9,
"10": 10,
"J": 10,
"Q": 10,
"K": 10,
"BlackJack": 10,
}
Is the dict I have
Okay but what do I put inside the dict?
what python version are you on?
3
minor version, too
eg 3.6, 3.7, 3.8, 3.9, 3.10, etc
if you don't know, you can use python3 -V and it'll tell you
3.10
gotcha
same syntax as typing.Dict[], but use dict[] instead
so the above would be dict[str,int]
class typing.Dict(dict, MutableMapping[KT, VT])```
A generic version of [`dict`](https://docs.python.org/3/library/stdtypes.html#dict "dict"). Useful for annotating return types. To annotate arguments it is preferred to use an abstract collection type such as [`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping "typing.Mapping").
This type can be used as follows:
```py
def count_words(text: str) -> Dict[str, int]:
...
``` Deprecated since version 3.9: [`builtins.dict`](https://docs.python.org/3/library/stdtypes.html#dict "dict") now supports `[]`. See [**PEP 585**](https://www.python.org/dev/peps/pep-0585) and [Generic Alias Type](https://docs.python.org/3/library/stdtypes.html#types-genericalias).
I see I see
but how would I typehint a list then?
lets say this is my list:
mylist = [1, 2]
typing.List[int]
it should be list[int] but someone said that it should be list[int, int]
whoever said that is wrong
Ah okay
also
in a class
if i want to typehint self, it should be self: object right?
why do you want to typehint self? @rustic gull
I'm trying to typehint as much as I can as it helps me understand what is what and how it works in depth etc..
just for learning
You should not typehint self most of the time
There are some rare times you should, in that case use a typevar:```py
F = TypeVar("F", bound="Foo")
class Foo:
def me(self: F) -> F:
return self
So I should not typehint when instantiating my class either?
hm?
like this:
game: object = Game()
```?
No, you shouldn't do that
Is there a particular reason for that?
are you using a type checker?
Nope
why are you using type hints then?
So I understand some stuff when reading my code?
they won't provide that much value, and you'll get them wrong, so other people will have a hard time
objectis not a very useful annotation. Everything is an object.- This will not let you do pretty much anything with
gamelater, because it's type hinted asobject.
ah I see
No, you should use a type checker π
What is that?
wait, its all objects?
It's a program that inspects type annotations statically and reports errors in your code.
Yeah everything in python are objects π€·
most popular is mypy, but pyright is becoming more popular
So it's a tool in the IDE?
IDEs have plugins for them, yes
lol I'm just gonna remove my typehints then xD, but how am I gonna understand what is what when reading and editing my code?
Nobody says you're not allowed to use type hints
my code will be long and it really helps knowing what is what without having to scroll to the section where I define it
idt that's the right takeaway. you shouldn't remove typehints rather start using a type checker
^^
I see, how would a type checker look like as an example?
what IDE are you using?
the thing is you just need to get the type checks right 
VSC
If you don't have the Pylance extension, install it.
If you do, go to settings -> Pylance -> type checking mode -> "basic"
boom, you have a type checker
now you should have pop-up hints:
and type errors:
bro...
im dumb af, why wouldn't i think of something like this
xD this is so smart
It works
Thanks! π
just fyi you can import typing_extensions and use Self in situations like this if you use vsc
But I should still typehint what a method is returning right?
yeah
i think self is provisionally in 3.10 rn
you would put the return type as Self
its not provisional in 3.10
3.11 then
its gonna hopefully be in 3.11
def start_cards(self) -> list[str]:
starting_cards = random.sample(list(self.card_deck)[:-1], 2)
if 'A' in starting_cards and any(card in starting_cards for card in ('10', 'J', 'Q', 'K')):
starting_cards.append(list(self.card_deck)[-1])
return starting_cards
So this for example, is fine for typehinting?
yep
Alright tysm guys
wow wait I have a bunch of errors in my other codes now?
I'm working on projects ranging from 3.6 to 3.9 π
i just future annotations
all these hacks break if you want to inspect the annotations
yeah
which is, to be fair, a niche thing
a niche thing
except for literally my entire project
90% of it is discord.py and attrs (dataclasses)
I have a question
go for it
a list is a class, and a object?
all classes are objects
so classes = objects?
but all animals aint dogs
I see
so there are different types of objects, such as classes?
types of objects are just 'types'
list is a type, str is a type, type is a type
the type of 1 is int, the type of "foo", is str, and the type of list is type
!e
print(type(1))
print(type("foo"))
print(type(list))
@trim tangle :white_check_mark: Your eval job has completed with return code 0.
001 | <class 'int'>
002 | <class 'str'>
003 | <class 'type'>
~~close enough~
int, str*
so 1 is int, a int is what? a list? a list is what? a type? a type is what? a class? a class is what? a object?
im confused
so strings arent actually string
Every object is an object (trivially).
Every integer is an object.
Every string is an object.
Every list is an object.
Every type is an object.
It's called "inheritance"
All types -- str, int, list etc. -- inherit from object
but what type is type π©
and what is a object π
!d object
class object```
Return a new featureless object. [`object`](https://docs.python.org/3/library/functions.html#object "object") is a base for all classes. It has methods that are common to all instances of Python classes. This function does not accept any arguments.
Note
[`object`](https://docs.python.org/3/library/functions.html#object "object") does *not* have a [`__dict__`](https://docs.python.org/3/library/stdtypes.html#object.__dict__ "object.__dict__"), so you canβt assign arbitrary attributes to an instance of the [`object`](https://docs.python.org/3/library/functions.html#object "object") class.
everything in python are objects of what I know, but why is it called a list?
What's called a list?
because if you called everything an object, it'd be very confusing very quickly
lists are called lists because they contain a list of objects
then wouldn't it be like: objects are classes, classes are objects?
it's circular?
Not all objects are classes. For example, "a" is not a class.
#type-hintingtheory
but it's still a object right?
yes, but not necessarily a class
I see
no
objectis a base for all classes
this means that all classes are objects, but not necessarily the other way around
!e ```py
print(issubclass(list,object))
@little hare :white_check_mark: Your eval job has completed with return code 0.
True
so:
mystring: object = "hello"
Is wrong, but actually right?
@little hare :white_check_mark: Your eval job has completed with return code 0.
True
So a person could actually typehint everything as a object
I see, that's why type exists right?
you generally don't need to typehint local variables, their types are automatically inferred
!e ```py
print(type(123))
!e print(type(123))
@little hare :white_check_mark: Your eval job has completed with return code 0.
<class 'int'>
But you can do this:
class Animal:
pass
class Dog(Animal):
pass
class ScaryDog(Dog):
pass
dog = ScaryDog() # inferred as ScaryDog
dog: Dog = ScaryDog()
dog: Animal = ScaryDog()
dog: object = ScaryDog()
dog: Union[Dog, int] = ScaryDog()
@rustic gull :white_check_mark: Your eval job has completed with return code 0.
<class 'int'>
all these are legal, because ScaryDog satisfies all of them.
Yeah I see
huh i just realised I should be using type() instead of __class__.....
also so this output actually means "object 'int'"?
since classes are objects
i'm not sure what you mean by that. it's just telling you that what you printed is the class int
and a class int = object?
ah i see, no you can't make that substitution
since classes support operations that object doesn't
err, at least, int doesn't
interesting
!e print(type(object))
@little hare :white_check_mark: Your eval job has completed with return code 0.
<class 'type'>
!e print(type(object()))
@little hare :white_check_mark: Your eval job has completed with return code 0.
<class 'object'>
wait object() is a builtin method?
its a call of class object
that is one long tag...
Classes
Classes are used to create objects that have specific behavior.
Every object in python has a class, including lists, dictionaries and even numbers. Using a class to group code and data like this is the foundation of Object Oriented Programming. Classes allow you to expose a simple, consistent interface while hiding the more complicated details. This simplifies the rest of your program and makes it easier to separately maintain and debug each component.
Here is an example class:
class Foo:
def __init__(self, somedata):
self.my_attrib = somedata
def show(self):
print(self.my_attrib)
To use a class, you need to instantiate it. The following creates a new object named bar, with Foo as its class.
bar = Foo('data')
bar.show()
We can access any of Foo's methods via bar.my_method(), and access any of bars data via bar.my_attribute.
!e
!eval [code]
Can also use: e
*Run Python code and get the results.
This command supports multiple lines of code, including code wrapped inside a formatted code block. Code can be re-evaluated by editing the original message within 10 seconds and clicking the reaction that subsequently appears.
We've done our best to make this sandboxed, but do let us know if you manage to find an issue with it!*
^ eval command
!d object
class object```
Return a new featureless object. [`object`](https://docs.python.org/3/library/functions.html#object "object") is a base for all classes. It has methods that are common to all instances of Python classes. This function does not accept any arguments.
Note
[`object`](https://docs.python.org/3/library/functions.html#object "object") does *not* have a [`__dict__`](https://docs.python.org/3/library/stdtypes.html#object.__dict__ "object.__dict__"), so you canβt assign arbitrary attributes to an instance of the [`object`](https://docs.python.org/3/library/functions.html#object "object") class.
oh there
All dogs are animals. Bob is a dog. Therefore, he's also an animal. Therefore, he's also a eukaryote.
But when someone asks "who's Bob?", you don't answer "he's a eukaryote", you answer "he's a dog"
I see I see
So basically, in the terms of a dummie, everything is a object, but there are different types in objects, such as a int, string, lists, classes etc..
^^ but when you typehint with object, that's limiting what you know about bob. You now only know he's an eukaryote. You now have hidden that he's an animal or dog from yourself.
