satwikkansal / wtfpython

What the f*ck Python? 😱
Do What The F*ck You Want To Public License
35.51k stars 2.65k forks source link

Solving simple equations #296

Open spielzeugland opened 2 years ago

spielzeugland commented 2 years ago

Hi, I have a proposal for a snippet around type annotations. Maybe the title could be a little more catchy.

▶ Solving simple equations *

# Writing a simple equation:
x : 1 = 4

# In verbal language:
# Some number x divided by one gives four. What is the number x?

Output (>= 3.6):

>>> x
4

Nice, Python can solve simple equations!

However, it does not work when dividing by other numbers. Why?

x : 2 = 7  # expecting x to become 14

>>> x
7

💡 Explanation:

The colon character is not a mathematical operator but the syntax for variable annotations introduced with PEP-526. It aims to provide type hints for IDEs and other tools like mypy for more static code checks which rule out a set of common mistakes during design time already like assigning wrong type:

# without type hints, you might accidentally assign wrong types, which might lead to all sorts of runtime issues
my_int = 42
my_int = "43"

# with type hints you would get linting errors e.g. using mypy already during development
my_int: int = 42
my_int = "43" 

By the way the preferred coding style for type annotations is like you see below.This was another attempt to visual trick you in the initial example.

x: int = 4
varunvora commented 1 year ago

The colon operator was not designed to solve equations. It was introduced for type hints in PEP 484.

Type annotations is not a well known feature. However, I don't think this issue fits in the context of this repository.

satwikkansal commented 1 year ago

In verbal language: Some number x divided by one gives four. What is the number x?

I agree with @varunvora, what is the basis for this?

spielzeugland commented 1 year ago

Of course it wasn't designed for it :-) It's also not working. It was more meant to be a joke like the existing "Teleportation" sample. But I think it's worth mentioning this for two reasons:

  1. advertisement for type annotations, which are powerful but unfortunately not well known feature (as you put it) especially in larger projects.
  2. it is valid syntax and might lead to issues. I once refactored code about some settings from using a dict to separate variables, but I missed to replace the ":" with "=". It was still valid python but not doing what I wanted.
options = {
    someFlag: 123
}

#after - still valid code, but not an assignment
someFlag: 123

Maybe I should give it a better name or make it more clear, what it actually does. What do you think?

varunvora commented 1 year ago

I see. There is a potential for errors if you do not know about type annotations. But if you look at the examples in README, this is not really a wtfpython example. Most examples show valid syntax but unexpected/counterintuitive output.

The examples you described are interesting because Python should have reported this as a syntax error but instead allows it. Not really a wtf in my opinion.

spielzeugland commented 1 year ago

That's exactly the point, it is valid python syntax. Unfortunately the specification does not describe the semantic of the type hint. Therefore the interpreter will not complain. And yes this was really a WTF python moment for me if you will.

PEP-526

since it [Python] will not care about the type annotation beyond “it evaluates without raising”, a type checker that encounters it will flag it

PEP-3107

By itself, Python does not attach any particular meaning or significance to annotations. Left to its own, Python simply makes these expressions available as described in Accessing Function Annotations below.

The only way that annotations take on meaning is when they are interpreted by third-party libraries. These annotation consumers can do anything they want with a function’s annotations. For example, one library might use string-based annotations to provide improved help messages, like so:

As stated above mypy complains with Invalid type: try using Literal[1] instead? Maybe IDEs like PyCharm do as well.

BTW in TypeScript (having a similar syntax for type annotations) the semantic of the typings are specified and the compiler complains:

var x : 1 = 4;
>> Type '4' is not assignable to type '1'. (2322)
satwikkansal commented 1 year ago

hmm, I think type annotations can be mentioned as a part of https://github.com/satwikkansal/wtfpython#-needles-in-a-haystack-

I frequently make the mistake of mixing : and = while working with Pydantic / dataclasses, for example

from pydantic import BaseModel

class User(BaseModel):
    user_id str
    name: str
    followers = int

I have made mistakes like this in rush, and I have seen similar ones in code reviews. Of course, it's a valid class definition, but the outcome is unintended.

And I think there might be some more subtle technical quirks that can be added as well, but I gotta read the docs for that :)

And yes, type annotations not having a side-effect (for example in the case of method args of a dataclass?) by default can be an interesting thing to demonstrate, I think that the majority of Python users know this, but not all.

1033786579 commented 1 year ago

您发给我的信件已经收到。我会尽快查看邮件。谢谢!