Strange and Cursed Python
Posted on 2024-09-19 08:19:25
This is a small post on some of the cursed, strange and outright daft python behaviours I have found. Python has a reputation for being simplistic and straightforward, leading to it being one of the most used languages in schools. Sometimes Python is not always as it seems.
- Numbers with the
is
function.
we all done if statements that areif x == y
and a few of you would have doneif x is int
orif x is y
well there a interesting behavior with ints.
x = 0
y = 0
while True:
x += 1
y += 1
if x is y:
print("x {} is equal to y {}".format(x, y))
else:
print("x {} is not equal to y {}".format(x, y))
if x > 260:
break
ill give you a sneak peak at the output before i explain why this is cursed.
x 253 is equal to y 253
x 254 is equal to y 254
x 255 is equal to y 255
x 256 is equal to y 256
x 257 is not equal to y 257
x 258 is not equal to y 258
x 259 is not equal to y 259
x 260 is not equal to y 260
The integers stop being equal to each other once they get bigger than 256
x -1 is equal to y -1
x -2 is equal to y -2
x -3 is equal to y -3
x -4 is equal to y -4
x -5 is equal to y -5
x -6 is not equal to y -6
x -7 is not equal to y -7
the same happens when it gets below -5 . In Python, small integers within a certain range are cached for efficiency reasons. This range -5 to256. Integers in this range are assigned to variables. They are stored as references to the same object in memory. Once we get past 256 orbelow -5, there are no premade objects, so new objects are created in different memory spaces, leading to them having different references.
- For Else. While may not be cursed its still a strange function very few people know off.
fruits = ["apple", "banana", "cherry", "date"]
# Search for a specific fruit
search_fruit = "carrot"
for fruit in fruits:
if fruit == search_fruit:
print(f"Found {search_fruit} in the list.")
break
else:
print(f"{search_fruit} not found in the list.")
This is an incredibly useful feature that people don't seem to discover. The else runs if the break statement does not run. If the break statement runs, then the else statement will be skipped. carrot
is not in the array, so we run the else statement saying that. if we were searching for cherry
, it found it while looping run the print and the break statement, then skipping the else statement. The else statement only runs after the full loop has run so the not after each if check.
- For a in a, Iterate through lists with a twist
I think the best way to explain this is show you the code and then explain the cursed bit.
a = [1,2,3]
for a in a:
print(a)
a.append(4)
and the output is
1
2
3
Traceback (most recent call last):
File "CURSED.PY", line 6, in <module>
a.append(4)
AttributeError: 'int' object has no attribute 'append'
So what we seeing here is two variables a
the list and a
the iterator. the iterator gets created and stores a reference to a place in memory for the list a at this point the name we given to the list does not matter as its going thought the reference. Once the list finishes running the reference of a is assigned to the value in this can 3 and the list is basically destroyed. And due to the list being destroyed we cannot add any new items.
a: print("setting variable 'a' to 5") = 5
So here, the variable a will be set to 5, and a print statement will run simultaneously on one line. This uses some interesting features behind match statements. What you see here is pattern matching. People must first understand that Python match statements are not switch statements. This is a common misconception that most people have.
match "hi":
case variable:
print("ran")
print(variable)
will output
ran
hi
So lets expaline why this behavour exists and spoiler its not to conuse your class mates
The primary use of matching is structural pattern matching. One of the biggest use cases for this would be matching inside a tree-like structure. Here are some examples of using syntax matching to perform basic arithmetic. We assign the ints to left and right then and check the operator to decide what case to use.
from typing import Union
def evaluate_expression(expr: Union[int, tuple]):
match expr:
case (left, "+", right):
return left + right
case (left, "-", right):
return left - right
case (left, "*", right):
return left * right
case (left, "/", right):
return left / right
case _:
return expr
print(evaluate_expression((5, "+", 3)))
print(evaluate_expression((5, "-", 3)))
print(evaluate_expression((5, "*", 3)))
print(evaluate_expression((5, "/", 3)))
- semicolons.
print("cat"); print("dog"); print("mouse") ; a = [1,2,3]
yes, it's valid you can use a;
to end a line on the same line to make those js users happy. Ok, fine I only included this so I can use a meme. There are some uses for this. suits can be one or more semicolon-separated simple statements on the same line as the header, following the header’s colon, or it can be one or more indented statements on subsequent lines. A example of this is if statements that your trying to fit inside other logic like a if statement inside a return of a functionreturn if x < y < z: print x; print y; print z
Thank you for reading my first real blog artificial. feel free to let me know what you though over on the mastdon or on the discord. If you enjoyed it consider buying me a coffee. And now time to leave you with a bit of cursed code
def even_or_odd(num):
"say if a number is even or odd"
return "eovdedn"[num % 2::2]
print(even_or_odd(2))
print(even_or_odd(3))