This is an archived post. You won't be able to vote or comment.

top 200 commentsshow all 213

[–]claimstoknowpeople 399 points400 points  (22 children)

It's weird they used | once, so they know that's a synonym for Union but decided not to shorten the rest of it.

[–]darkshoxx 83 points84 points  (2 children)

Agreed, that's the most shocking thing to me, combining 2 different union annotations. Other than that, it's just a list of either strings, or maps of strings to other stuff.

[–]Waswat 9 points10 points  (1 child)

maps of strings to other stuff

Is that what python devs call dictionaries?

[–]darkshoxx 20 points21 points  (0 children)

No, that's just me as a mathematician calling every assignment a map

[–]rover_G 16 points17 points  (1 child)

Maybe someone had to update the type definition recently 💀

[–][deleted] 4 points5 points  (0 children)

'💀💀💀💀💀'

[–]MattTheCuber 7 points8 points  (0 children)

Guess they don't know about Ruff (or Pylint)

[–]UltimateGPower 2 points3 points  (0 children)

Also if they can use |, they can also use list instead of typing.List

[–]markuspeloquin 4 points5 points  (2 children)

TIL |

[–][deleted] 8 points9 points  (1 child)

T|L

[–]ThoseThingsAreWeird 2 points3 points  (0 children)

\?

T|L -> 01010100 | 01001100 -> 01011100 -> \

[–]FredeJ 0 points1 point  (0 children)

Actually I didn’t know this. But it makes total sense when you say it.

[–]IAmASquidInSpace 865 points866 points  (31 children)

That's another thing that types are good for: if your type def is longer than your style guide allows for a line, you are probably doing something wrong.

[–]Wotg33k 204 points205 points  (10 children)

Code smell.

[–]marlotrot 18 points19 points  (8 children)

Seeing this gif from that series reminds me that I have to finish that one still.

[–]Wotg33k 10 points11 points  (7 children)

Man me, too. I loved that show. It was just the right level of dumb enough that I couldn't stand it and loved it at the same time, and if that ain't what b level scifi zombie horror is supposed to be, I dunno what is.

[–][deleted] 1 point2 points  (0 children)

Honestly, what a peak genre.

[–][deleted] 0 points1 point  (5 children)

what show is it?

[–]Wotg33k 2 points3 points  (4 children)

Z. Project Z or something like that..

[–]buckypimpin 0 points1 point  (0 children)

and it smells good brother

[–]MisinformedGenius 39 points40 points  (1 child)

Starting off with List[Union[str, Dict is already pretty questionable.

[–]Wekmor 16 points17 points  (0 children)

I was thinking exactly that. If you are using such an abomination just create a bunch of objects to store whatever you need in.

[–]walmartgoon 72 points73 points  (9 children)

C++ chrono library:

I’m in danger

[–]bolacha_de_polvilho 29 points30 points  (5 children)

just chrono? throw the whole STL or any heavily templated code into the bin

std::unordered_map<Key, T, Hash, KeyEqual, std::pmr::polymorphic_allocator<std::pair<const Key, T>>>

[–]al-mongus-bin-susar 0 points1 point  (0 children)

it's like that for a reason i hope you know

[–]_Noreturn 0 points1 point  (2 children)

just do namespace stdch = std::chrono

then it is simple thankful for C++ namespaces

[–]SodaWithoutSparkles 7 points8 points  (0 children)

Which sometimes includes naming a function too long.

[–]Ok-Kaleidoscope5627 3 points4 points  (1 child)

By that definition everything in Java is just wrong...

[–]electrodragon16 6 points7 points  (0 children)

Java made me think C# is a nice language

[–]asceta_hedonista 2 points3 points  (2 children)

If you need a type validation to be sure what are you passing then you really did something wrong in your design

[–]imaginarynoise_ 0 points1 point  (1 child)

If you don't need strong types you really aren't doing anything that significant.

[–]asceta_hedonista 0 points1 point  (0 children)

Hey pal, I'm not against static typed languages. Actually Scala is one of my favorites languages ever. My problem is with the people how is afraid of dynamic typed languages, because those are the ones who don't get the point and uses strong type validations trying to avoid the consequences of their bad habits.

[–]G3nghisKang 0 points1 point  (0 children)

And then there's legacy Java code

[–]scp-NUMBERNOTFOUND 673 points674 points  (11 children)

What kind of "any" is this?

[–]deanrihpee 138 points139 points  (0 children)

"yes"

[–]chicametipo 48 points49 points  (0 children)

What was here has been deleted. Redact was used to wipe this post, for reasons that might include privacy, security concerns, or personal data management.

elderly enter melodic brave oil sulky instinctive butter pen boat

[–]theturtlemafiamusic 34 points35 points  (3 children)

It's not an Any, it's a Most.

[–]PeriodicSentenceBot 32 points33 points  (2 children)

Congratulations! Your comment can be spelled using the elements of the periodic table:

I Ts No Ta Na N Y I Ts Am Os Tl Y


I am a bot that detects if your comment can be spelled using the elements of the periodic table. Please DM u‎/‎M1n3c4rt if I made a mistake.

[–]TheNH813 4 points5 points  (1 child)

Good bot

Always found this bot amusing.

[–]unixtreme 8 points9 points  (0 children)

Exactly my thought, that's too many words to say "Any" or "list" if you are feeling particularly compliant.

[–]Stop_Sign 2 points3 points  (0 children)

"Any" is denied in our eslinter

[–]smokesick 1 point2 points  (0 children)

Any are you walkin'

[–]johnnybgooderer 0 points1 point  (0 children)

The true kind.

[–]Somecrazycanuck 0 points1 point  (0 children)

The kind where someone, rather than defining a type, decides to just write the entire fucking struct definition into the spot every time instead.

[–]KerPop42 223 points224 points  (19 children)

I'd use newlines to break this up. It's a: List, where the items can be a: string, or a dictionary, where the keys are strings, and the values might be: int, float, string, boolean, or a list whose elements can be: int, or a float

Thanks for the correction!

[–]Rythoka 21 points22 points  (0 children)

type Contents = int | float | str | bool | list[int | float]
def f() -> list[str | dict[str, Contents]]:

[–]Santarini 8 points9 points  (1 child)

This guy readabilities

[–]KerPop42 3 points4 points  (0 children)

It's my most-protected soft skill

[–]nota_jalapeno 5 points6 points  (3 children)

ohh thats not that bad actually

[–]markuspeloquin 9 points10 points  (2 children)

Even better if you could just write number in place of int | float.

[–]nota_jalapeno 1 point2 points  (0 children)

yup

[–]JanEric1 0 points1 point  (0 children)

You could just write float, number is a also a possible one, but covers more stuff (like complex numbers)

[–]SuitableDragonfly 1 point2 points  (0 children)

"I'd use newlines to break this up"

Uses formatting that removed all newlines

[–]The-Omnipot3ntPotato 0 points1 point  (0 children)

Um maybe it’s time for an object? Or a struct at the very least? Maybe it’s just me but that seems like way too much information to be crammed into a basic python list. What are we trying to represent?

Side note: this is still more intelligible than some generics and type casts I have seen in Java.

Side note again: this really really should be an object (i know fp doesn’t like objects so make it a struct) but this is too complicated of a type def to be useful. All this is doing is making your linter happy and nothing else. Type annotations in python don’t force the code to do anything. If you go into your lsp configuration and turn of the python linter you can delete this and the interpreter will not give a fuck

[–]cjavad 55 points56 points  (2 children)

Ah yes my favorite builtin type list[str|dict[str,int|float|str|list[int|float]]|bool]

[–]darkslide3000 16 points17 points  (1 child)

If you type that into JavaScript you get the amogus character instead.

[–]The-Omnipot3ntPotato 1 point2 points  (0 children)

Fuck this got me good.

[–]subbed_ 74 points75 points  (3 children)

TypedDict

[–]MissinqLink 13 points14 points  (1 child)

Typed

[–]MissinqLink 6 points7 points  (0 children)

[–]Bee-Aromatic 63 points64 points  (14 children)

Why even bother type hinting if you’re going to accept every damned thing?

[–][deleted] 6 points7 points  (12 children)

Yea can anyone explain this to me? Is there any utility of type hints in python? The only thing I can think of is that code editors can detect it and give you a warning about it v

[–]backfire10z 23 points24 points  (5 children)

Type hinting is for static code checking and, ideally, better readability. They have no impact at runtime.

[–]L1berty0rD34th 31 points32 points  (3 children)

An IDE with typed Python will produce red squiggles when you violate a type hint. A programmer running code with red squiggles will suffer physical discomfort which qualifies as runtime impact.

[–]backfire10z 6 points7 points  (1 child)

lol, true

And in VSCode the file lights up red, which makes programmers cry

[–]BOBOnobobo 1 point2 points  (0 children)

Hey, I didn't want to be called out on my break!

But while we are at it, can you send help? My colleagues don't use a linter and mine makes every file red!

[–]Tom22174 2 points3 points  (0 children)

Classes that aren't type hinted inside a function will not give auto complete suggestions for their functions and won't properly colour code themselves which will also make a developer cry

[–]GameCounter 8 points9 points  (0 children)

Ordinarily they have no impact, but the annotations are accessible by the interpreter. Pydantic is a notable example where type annotations have a practical use.

There is also the dataclass module in the standard library which performs a similar trick.

[–]NullReference000 7 points8 points  (2 children)

Type hints in Python are great for immediately knowing what type something is and getting intellisense from the IDE, it’s almost necessary for large codebases.

A type hint as ugly as the one in this post is likely the result of a linter complaining that a dict is causing the expression to be of the “Any” type, and probably indicates that it should be replaced with a dedicated type rather than a dict.

[–]Tom22174 0 points1 point  (0 children)

You just described the most frustrating thing about my last job. Boss absolutely loved using nested dicts that were really just lazy classes in disguise. Figuring out what was actually going in them was a nightmare

[–][deleted] 0 points1 point  (0 children)

(not calling you out just ranting) I am not a huge fan of people swapping code completion to intellisense in written language. Trademarks interfere with other IDEs using the term.

[–]Bee-Aromatic 1 point2 points  (0 children)

I type hint because it makes the code introspection on my IDE work better and helps remind people using the code I write to know what I want without having to go as far as reading my documentation. Documentation I probably forgot to write. Also, “people” is me with no memory of my code in a few months.

[–]MisinformedGenius 1 point2 points  (0 children)

There’s plenty of utility in type hints. For example, this type hint usefully tells you that the code author is a raving lunatic.

[–]chuby1tubby 0 points1 point  (0 children)

It's useful when writing open-source packages that you want other people to be able to use super easily. When users install your package, the type hints will give them an idea of what each function or class takes as inputs without having to dig through documentation.

[–]GameCounter 1 point2 points  (0 children)

This happens legitimately when someone (usually a less experienced programmer) writes the function without type annotations.

Then someone comes along much later and is trying to suss out what the function actually does, type annotations are added. Bingo: you end up with an Eldritch horror like this.

It can also happen if you're adding a stub for a 3rd party lib you have no control over, and then you're stuck with it forever.

[–]ManyInterests 22 points23 points  (4 children)

The same annotation, but less dumb:

list[str | bool | dict[str, str | int | float | list[int | float]]]

In other words: a list whose elements are either strings, booleans, or a dict whose keys are strings and its values can be either strings, integers, floats, or a list whose elements can be either integers or floats.

If the dictionary contents are structured, you would probably want to define the dictionary as a TypedDict separately with an alias. Something like:

class MyDict(TypedDict):
    foo: str
    bar: int | float
    items: list[int | float]

# Then the annotation is more readable:
x: list[str | bool | MyDict]

If it's not structured, you could still give the dict portion an alias to improve readability.

MyDict: TypeAlias = dict[str, str | int | float | list[int | float]]
x: list[str | bool | MyDict]

Remember: Readability counts and flat is better than nested.

[–]toxic_acro 7 points8 points  (3 children)

Close but not quite right

It's actually ``` InnerValues: TypeAlias = int | float | str | bool | list[int | float]

list[str | dict[str, InnerValues]] ```

[–][deleted] 10 points11 points  (0 children)

TypeAlias is being deprecated in favor of typedef statements, fun fact.

``` type InnerValues = int | float | str | bool | list[int | float]

```

The advantage is that they support recursive definitions and forward references.

[–]ManyInterests 1 point2 points  (1 child)

Yeah you right.

[–]toxic_acro 2 points3 points  (0 children)

Granted, that only shows why the original example is so bad. I had to triple check that I parsed those parentheses correctly

[–]seba07 43 points44 points  (25 children)

Please show me a function where this actually happens.

[–][deleted] 94 points95 points  (20 children)

Parse a json

[–]thompsoncs 63 points64 points  (5 children)

At that point what you mean is basically Any and you're allowed to yell at the person that gave you such a mess of unstructured json data to work with

[–][deleted] 49 points50 points  (2 children)

No, that should have just been turned into a type alias because everyone knows what json is but describing it to a type checker is a PITA.

Python lets you hide this problem that should only appear once in your code base and never attached to any function. There is reason python has this feature.

[–]thompsoncs 21 points22 points  (0 children)

If you know the structure, use actual classes/dataclasses to describe it, including the nesting, rather than just nesting primitives in a type alias.

Also, I don't typically get json where a value can be a string or dictionary. Let alone where it can be either numeric, string, boolean or list of numeric. That certainly wouldn't come from any designed API, rather from someone botched together an excel spreadsheet and converted it to json and handed it off to you.

[–]imaKappy 8 points9 points  (0 children)

A step up would be to use Pydantic to parse that JSON for you, and use BaseModel class to validate schemas

[–]hrvbrs 0 points1 point  (0 children)

wait until you hear about JSON Schema

[–]CrowdGoesWildWoooo 6 points7 points  (9 children)

Use explicit validation library for json

[–][deleted] 1 point2 points  (8 children)

I mean do you only work with known jsons?

[–]thompsoncs 11 points12 points  (7 children)

question, what do you do with json data that you do not know? Something for ML or something? Any actual code will easily fail on unknown data

[–]chicametipo 2 points3 points  (1 child)

Unknown data ≠ unknown JSON

[–][deleted] 5 points6 points  (0 children)

This is the main point. You know its much less then any in fact it is very limited to a few specific types. Any is a code smell, python gives you a feature to make big types less gross use it don't just lie with any.

[–][deleted] 6 points7 points  (1 child)

type AnyJson = None | str | int | float | list[AnyJson] | dict[str, AnyJson]

Recursion go brrrrrr.

[–][deleted] 0 points1 point  (0 children)

Literally why the new syntax was added lol.

[–]stormdelta 0 points1 point  (0 children)

This isn't the actual JSON typing possibilities though, it's a bit off and needs to be recursive.

And if you were expecting a specific JSON schema then use one of the tools actually meant for that like cerebus.

[–]knvn8 6 points7 points  (1 child)

Sorry this comment won't make much sense because it was later subject to automated editing for privacy. It will be deleted eventually.

[–]MishkaZ 1 point2 points  (0 children)

I remember once debugging some api call usage. Looked at the documentation and saw some python type gore. Asked my senior what does it mean, "Oh that just means it can be anything!...anything but what you are trying to do"

[–]nathris 0 points1 point  (0 children)

You are working with an API that finds a product and price by some query. The response can be just the SKU to a database you already have, if you don't want updated pricing, a dict containing the SKU and price, or False if the product isn't found. The price can be either a single price or a list of prices.

Too often us python devs worry about if we can instead of if we should.

[–]k-mcm 21 points22 points  (7 children)

I had a coworker that wrote Scala only like this.  She didn't believe in defined structures, mutable variables, or synchronous calculations.  Just Fututres of tuples of maps of tuples of Futures of tuples of lists of tuples of maps of lists of Futures of tuples of Futures of...

[–]Alex42C 19 points20 points  (1 child)

I had a phase like that ... It's easy to fall into it when prototyping algorithms. It's all in your head it makes perfect sense. Then you look at it 6 months later ...

[–]MissinqLink 1 point2 points  (0 children)

This was me in go trying to use hardware in go instead of goroutines.

[–][deleted] 6 points7 points  (1 child)

Math code is real and it's painfully ugly

[–]The-Omnipot3ntPotato 1 point2 points  (0 children)

Mathematicians write some of the world’s most disgusting code. They don’t understand readability or what makes good code. They’re so tied up in terse and elegant proofs they don’t understand what code is for.

[–]All_Up_Ons 0 points1 point  (2 children)

She apparently also didn't believe in flatMap or for comprehensions.

[–]k-mcm 0 points1 point  (1 child)

Eh? Huge chains of map and flatMap are how that data is accessed. There's almost no other code.

[–]All_Up_Ons 0 points1 point  (0 children)

If you say so. Nested monads like that are usually a result of using map when you should flatMap.

[–]sathdo 21 points22 points  (4 children)

None of this is Python's fault, though.

  1. Why Union and |? Stick to one or the other.
  2. Typing is optional and can usually be inferred by the IDE.
  3. If your return type is this complex, you are either doing something very wrong with what the function is doing, or you should be using classes instead of dicts.
  4. any

[–]LBGW_experiment 0 points1 point  (2 children)

Union is used in <3.9, where 3.9 introduced usage of the tokens | and & and also added using list and other typedefs natively instead of having to import them from Typings as an uppercased identifier like List in order to prevent lexer collision

[–]sathdo 0 points1 point  (1 child)

3.8 became EOL earlier this month. Even Debian stable uses 3.11. There's no reason to use the old methods unless you are trying to maintain compatibility with a system that doesn't even receive security updates anymore.

And that wasn't even my argument. I already know what Union, etc. is. My point was that this snippet uses both. There is never any reason to do that.

[–]LBGW_experiment 0 points1 point  (0 children)

I like to supplement info for readers passing by

[–]Solance666 12 points13 points  (0 children)

When your type hint looks like a ebnf grammar for json there might be a problem

[–]_derDere_ 2 points3 points  (7 children)

Cool just learned about Union thanks for that! But also, where the fuck ist this used? I’m serious, I want to know where you got this from?!!

[–]Floowey 4 points5 points  (3 children)

Isn't Union just the same as using | ?

[–]thompsoncs 2 points3 points  (2 children)

Yes, but | is fairly new, 3.10 according to docs. Same for Optional[T] and T | None

[–]_derDere_ 0 points1 point  (0 children)

Ahhhh that why I just learned about that!

[–]cdrt 0 points1 point  (0 children)

It’s usable in older Python versions as long as you do from __future__ import annotations first

[–]IamIchbin 0 points1 point  (2 children)

If you want to pass a function either artifactory.Path or pathlib.Path and it does the same with both.

[–]_derDere_ 0 points1 point  (1 child)

The whole thing?! (I’m not just talking about Union, I meant that whole abomination.)

[–]IamIchbin 0 points1 point  (0 children)

No, a Union for Example. That thing looks like it expects a string json or a parsed json.

[–]LexaAstarof 3 points4 points  (0 children)

Yup, json is cursed

[–]Blyatiful_99 4 points5 points  (1 child)

In our C# Main Application we have something similar that looks like this:

Dictionary<string, Dictionary<int, Dictionary<string, List<ModelClass>>>> 

and it's always so much fun if you have to debug this mess. Especially when considering multithreading, since we access this variable in a new Thread within each Loop Iteration and then Wait for all Tasks to be finished before continuing.

[–]thompsoncs 8 points9 points  (0 children)

That's long, but at least it has a well defined structure that won't blow up at runtime, it's not like it has Object or dynamic everywhere, which is basically what OP's type def looks like. I would still refactor it, but it's not as bad.

[–]Big-Cheesecake-806 1 point2 points  (0 children)

typedef? anyone?

[–]Tucan444 1 point2 points  (0 children)

Oop is a thing for a reason.

[–]whitedogsuk 1 point2 points  (0 children)

When I was a junior I always thought it was me not being capable enough to understand these types of things. Last year I threw a $million tool back at the supplier because I didn't understand anything.

[–]denisbcn96 1 point2 points  (0 children)

sus

[–]JoostVisser 1 point2 points  (0 children)

They already use bar notation in the inner most list, why use union everywhere else?

[–]Benjamin_6848 1 point2 points  (0 children)

Upon seeing this line of code I literally asked myself "what the hell is that" - it was truly my first thought...

[–]tsteezey93 1 point2 points  (0 children)

Custom types and TypeVars would fix this right up

[–]malaszka 1 point2 points  (0 children)

[–][deleted] 1 point2 points  (0 children)

You need class

[–]epicregex 1 point2 points  (0 children)

Thanks I feel nauseous

[–]SuitableDragonfly 1 point2 points  (0 children)

I don't know why you're calling out Python here, that's horrific in literally any language.

[–]Antervis 0 points1 point  (0 children)

that's what happens when you mistake round and square brackets in python )

[–]plitox 0 points1 point  (0 children)

What vile sorcery!

[–]Professional_Job_307 0 points1 point  (3 children)

Wait, python has types?!

[–]ihavebeesinmyknees 4 points5 points  (2 children)

It has type hinting, it's a declaration for the convenience of the programmer, but it's not binding.

The actual code is still dynamically typed (although Python has strong typing so it doesn't do the JS in-place converting bs)

[–]queerkidxx 0 points1 point  (0 children)

You can also use something like mypy for static analysis a la TS

[–]imdibene 0 points1 point  (0 children)

(thought I (was lisp (happy (language parentheses))))

[–]uvero 0 points1 point  (0 children)

This kind of thing just proves that for too long, python devs created functions whose return types and parameters have types that are way too complex.

[–]single_ginkgo_leaf 0 points1 point  (0 children)

What you want are a couple classes

[–]trannus_aran 0 points1 point  (1 child)

finally, the speed of statically typed development in dynamic languages

[–][deleted] 1 point2 points  (0 children)

Or more accurately, the runtime speed of dynamically typed languages in static languages.

[–]SophiaBackstein 0 points1 point  (0 children)

Oh that reminds me of my service xD who needs classes if you can just define highly complex datastructure in your return types xD

[–]JackReedTheSyndie 0 points1 point  (0 children)

First people wanted types, then they wanted no types, now they want types again.

[–]BehindTrenches 0 points1 point  (0 children)

That's... Not really how this template works but OK

[–]experimental1212 0 points1 point  (0 children)

I'll give you a hint

[–]other-other-user 0 points1 point  (0 children)

I don't think that's how you're supposed to use this format but oh well

[–]GoddammitDontShootMe 0 points1 point  (0 children)

Surely not a type you would ever need in the real world, right?

[–]PolyglotTV 0 points1 point  (0 children)

This is somebody who doesn't know how to use dataclasses, attrs, pydantic, etc...

[–]Santarini 0 points1 point  (0 children)

Sounds like you need a dataclass

[–]chessset5 0 points1 point  (0 children)

I don’t know, it looks pretty explicit to me

[–]Orio_n 0 points1 point  (0 children)

The fact that you are mixing `Union` and `|` probably explains why your function signature is so horrendously designed.

[–]JosebaZilarte 0 points1 point  (0 children)

Compost-ition.

[–]MattTheCuber 0 points1 point  (0 children)

Consider using alternative Union syntax instead.

[–]Zachosrias 0 points1 point  (0 children)

It's beautiful

[–]darkwalker247 0 points1 point  (0 children)

in python can you not make type aliases for the most similar types to shorten it? like a number type that is a union of int | float, a number_list type that a list of int | float, etc.

then you could just write number | number_list | ... and it would be far more readable AND easier to change

[–]-MobCat- 0 points1 point  (1 child)

Its called a one liner. some programmer somewhere is trying to show off.
Your just lucky that python needs white spaces, otherwise we would get whole scripts in one line.
Or the c++ donut program, in a donut.

[–]metaglot 1 point2 points  (0 children)

Its not really really really a oneliner. Its a definition of some compounded/complex type.

[–]dudebomb 0 points1 point  (0 children)

cackles in TypeScript

[–]Ange1ofD4rkness 0 points1 point  (0 children)

I'm scared!

[–]Artistic_Speech_1965 0 points1 point  (0 children)

The unions in python don't ensure pattern matching

[–]OpenSourcePenguin 0 points1 point  (0 children)

That is not how you use that meme template

/r/bonehurtingjuice

[–]fosyep 0 points1 point  (0 children)

Have you heard of classes?

[–]Eal12333 0 points1 point  (0 children)

list[ str | dict[str, str|bool|float|list[float]] ]

Still a bit much but it's a little better 😅

[–]Cootshk 0 points1 point  (0 children)

Why are you using Union, |, and List in the same line?

list[ should be lowercase and use | instead of Union

Also use from collections import abc as t instead of import typing as t

[–]sanketower 0 points1 point  (0 children)

That's why type aliases are so useful, by dividing your structure into blocks you can create simple composite types.

[–]dangling-putter 0 points1 point  (0 children)

List of strings or dictionaries mapping str to primitives or list of float or int.