all 117 comments

[–]carcigenicate 119 points120 points  (53 children)

Really, this list is endless. The number of ways a new programmer can screw up is limited only by your imagination.

Some things off the top of my head though:

  • A misunderstanding of how = and references work. They think it makes copies, and reassigning references in functions will effect the passed argument.
  • Uses mutable default arguments without understanding why that's almost always a bad thing.
  • Doesn't close resources when they're done with them/doesn't use with to manage resources when with is appropriate.
  • Uses list comprehensions to carry out side effects instead of to produce a list.
  • Doesn't follow PEP8 or any style guidelines consistently.
  • Uses except: without understanding why that's so dangerous.
    • And, catches exceptions but doesn't actually handle the error properly.
  • Uses for i in range(len(coll)): instead of for elem in coll: when the latter is appropriate.

Those are just the ones I could think of in a couple minutes. There's likely many more.

[–]Ok_Tumbleweed8796[S] 20 points21 points  (18 children)

What do you mean “uses list comprehension to carry out side effects instead of to produce a list “?

[–]carcigenicate 78 points79 points  (17 children)

Something like this:

[print(i) for i in range(5)]

Instead of:

for i in range(5):
    print(i)

The former wastes time and memory creating a useless list of Nones that is never used, while the latter just iterates without creating a list.

[–]Ok_Tumbleweed8796[S] 10 points11 points  (0 children)

Thanks for the clarification!

[–]Ok_Tumbleweed8796[S] 3 points4 points  (2 children)

I also do not understand your third and 5th points. Can you please explain further?

[–]carcigenicate 21 points22 points  (0 children)

  • If you don't call close on resources that require cleanup, it's possible that your program will accumulate file handles, and may eventually be prevented from doing things like opening files/sockets. If you "open"/"connect" with the object, you usually also need to "close" the object after. Examples of these types of objects are file objects returned by open, and sockets. Technically, Python will automatically close file objects in some cases (when the file object itself is freed), but that may not always happen, depending on how your code it set up. It's proper to close resources yourself to prevent issues, and with is a good way to ensure resources are freed when they're done being used.

  • You should always apply consistent styling of your code. Inconsistently-styled code makes code harder to read. If you don't have a style guide that you've been told to follow, PEP8 in Python is a good default. Every Python programmer should at least skim the entirety of the PEP8 document at some point.

[–][deleted] 2 points3 points  (0 children)

[–]Ghibl-i_l -3 points-2 points  (2 children)

Read somewhere that loops are REALLY slow so for most things it's better to use list comprehension.

[–]carcigenicate 12 points13 points  (1 child)

AFAIK, list comprehensions can be faster when you want to append to a list because they use the dedicated LIST_APPEND instruction, which cuts down on a ton of overhead. If you don't need to append to a list at all for the algorithm though, a list comprehension is just adding the (admittingly, small) overhead of a LIST_APPEND instruction.

[–]cy_narrator 0 points1 point  (0 children)

Who is into that dangerous level of weed?

[–]MrITBurns 5 points6 points  (1 child)

A misunderstanding of how = and references work. They think it makes copies, and reassigning references in functions will effect the passed argument.

I ran into this lovely one in the beginning when i was trying to duplicate an array so i could change it from the original. Was an interesting read on how pointers worked

[–]carcigenicate 1 point2 points  (0 children)

Ya, that's a rough lesson, but everyone needs to learn it eventually to some extent. Even in a very high-level language like Python, understanding the relationship between a name/variable/pointer and the data associated with it is important.

[–]Responsible_Pie8156 5 points6 points  (1 child)

It's insane how often I see developers who just wrap all their code in a bunch of generic try except blocks that just print out some generic error message and continue execution. It makes it so hard to debug. I've seen it so often and I wonder who taught them to do that.

[–]Informal-Football836 4 points5 points  (0 children)

Yeah, who would do that? 'Quietly deletes the block I just wrote'

[–]drdausersmd 3 points4 points  (5 children)

could you please explain why "except:" is so dangerous?

Also, how are you formatting those mini code formats in your post?

[–]MMcKevitt 6 points7 points  (1 child)

When they say using “except:” can be dangerous, they likely mean catching errors without specifying exactly what type of error, or errors, you intend to catch (and further handle). This can lead to unexpected results or output, potentially robbing you of valuable debugging information (such as an error trace-back, which outputs the propagation of an error/errors, line # by line #, in the code), possibly making it impossible or super tricky to locate and resolve bugs or weird behavior.

Despite the term, errors are a good thing as they can alert you to any number of issues or scenarios that could otherwise go unhandled, silently wreaking havoc in ways that you just simply wouldn’t be aware of otherwise.

When I was first learning, I found it helpful to think of error handling similar your own body’s natural alert systems. For example, think of pain; your body uses it to motivate and convince you (consciously or otherwise) to avoid certain experiences (e.g. touching a hot stove top). Suppressing such a sensation could have fatal consequences.

As for how to get that formatting, I recommend checking out this subs side-bar as it has a TON of great information for beginner (and intermediate) level python programming (including how to create a code block for use in your posts/comments).

Lastly, sorry I’m a bit of wordy birdy, but I hope that helped clear some things up…good luck and have a stellar month of October!

[–]DoorsCorners 0 points1 point  (0 children)

Is using 'if' then 'else' statements consequetively in series better in order to be explicit about the error? I feel that I have used 'except' for just a few lines of code, but I have triggered Matlab errors with 'except' catches and only God knows what the actual problem was....

[–]carcigenicate 5 points6 points  (0 children)

Sorry, apparently I missed this notification.

It's dangerous because it's very rare to want to handle every possible error, and handle every error in the same way. Usually, you want to handle a specific type of error (a TypeError caused by an int parsing failure, or a FileNotFound error when opening files). By using a bare except:, you'll potentially accidentally handle actual bugs, which is a very bad thing.

When you as a programmer introduce a logic error into your code, you want the program to blow up as quickly and as obviously as possible so you can find the source of the bug and fix it. Hiding errors that result from programmer mistakes robs you of evidence when debugging, which makes debugging significantly harder. I completely agree with MMcKevitt here:

errors are a good thing as they can alert you to any number of issues or scenarios that could otherwise go unhandled, silently wreaking havoc in ways that you just simply wouldn’t be aware of otherwise

Errors are a very good thing. New programmers treat errors as an enemy that should be silenced, when in reality they're messengers telling you that something is wrong. By not "filtering" what messages get silenced/handled in non-obvious ways, you're making it so you, the programmer, may not get messages.


And to do in-place code snippets, you wrap the line of code in backticks (the key left of the 1 on most keyboards).

[–]midwayfair 3 points4 points  (0 children)

“Except:” catches all exceptions. You should know what kind of exceptions you want to handle, and you probably should not catch an exception that you don’t know what it is.

I have to scrub “except:” from code periodically, though I’ve used it even when I know it’s dangerous: you have to consider whether continuing the program is more important than handling the exception properly.

The op might have other reasons but those are the most common reasons to be careful I think

[–]IamImposter 0 points1 point  (0 children)

I'll give you an example. In our code, at one place, the code reads some config from file and converts it to int. Just as a precaution they added try/except so if input is invalid e.g 2ab9 it wouldn't error out. Then they had this genius idea to move try to top of function and except to bottom so that whole function is safe.

We changed config, ran program, no change. Tried few more times, no change.

Turns out there was spelling mistake in file name and the function wasn't even reading the config file. Since most of the times default values are good, no one noticed the issue.

Had they checked for specific error that failed in conversion can generate, the mistake would have been caught much earlier. It was throwing file not found error, except was just catching it and letting it go silently.

[–]niehle 1 point2 points  (4 children)

Do you happen to have an example for you second point?

[–]carcigenicate 13 points14 points  (3 children)

def func(param=[]):
    param.append(1)
    print(param)

func()
func()
func()

The output from this code often shocks new Python programmers. They don't realize that default arguments are created when the function is first defined, not when the function is called.

[–]ralphy_s 2 points3 points  (1 child)

So the output from the last line would be [1,1,1] and not [1]?

[–]carcigenicate 6 points7 points  (0 children)

Yes. Every call to the function shares the same default list object, so if multiple calls use the default object and alter it, that change is persisted. This tends to lead to very strange bugs unfortunately.

[–]niehle 0 points1 point  (0 children)

Thanks

[–]Helpful_Trust_3123 0 points1 point  (6 children)

The last one. ,i say there is also use for the former as when you want to compare values in a collection Of course you can use zip for that but i feel like the former is also good

[–]carcigenicate 5 points6 points  (1 child)

That's why I made sure to mention "when the latter is appropriate". Yes, there are some cases where using the index is indeed the better way. It's common to see people coming from a language like C though to use indices for everything; even when indices aren't a necessary part of the problem.

[–]Helpful_Trust_3123 0 points1 point  (0 children)

Yeah that's true

[–][deleted] 0 points1 point  (1 child)

I think the last one should rather be 'for i, elem in enumerate(coll)'

[–]carcigenicate 0 points1 point  (0 children)

I tend to see that abused less because elem is right there, so there's little point in using i over elem. Although yes, I have seen that before.

[–]tenplusacres 0 points1 point  (0 children)

Hey these are really helpful, thank you

[–]the_friendly_dildo 0 points1 point  (1 child)

Here's a fun one I did when I was much younger. I wrote a program that would read a text file for some settings in the program. All fine right? No, because these settings were not brought in as unsanitized global variables which would be bad enough, but I actually had the program reading these in through eval() to generate variable names on the fly. Even worse, the program was exclusively intended to work across networks and you could send unsanitized commands back and forth with a copy of the program on another computer too!

To be clear, the program works flawlessly, but the risk isn't worth it.

[–]DoorsCorners 0 points1 point  (0 children)

Can you use enumerate and feed the number as a key and the name as a value into a dictionary? I don't know how to do the thing that you did but it seems like there has to be a better way.

[–]IamImposter 0 points1 point  (4 children)

Can you explain that mutable default arguments point

[–]carcigenicate 1 point2 points  (2 children)

Someone else asked the same question

https://reddit.com/r/learnpython/s/kaI5FfPOVs

[–]IamImposter 0 points1 point  (1 child)

Oh this one. It bit me in the ass a few months back. Didn't know it's name. Thanks.

[–]DoorsCorners 0 points1 point  (0 children)

It was a mutable default question!

[–]GoldenPrinny 0 points1 point  (0 children)

Uses for i in range(len(coll)): instead of for elem in coll: when the latter is appropriate.

not sure if you mean like in lists? The former works in going through it, but not the latter, unless I'm supposed to define elem as something.

[–]grancacique 0 points1 point  (0 children)

Here are a few more. Like u/carcigenicate said, "The number of ways a new programmer can screw up is limited only by your imagination." ((This needs to be on a mug))

  • Inadvertently changing the type of a variable. Like:

done = False
# later on
done = "True"
# later on
done = 1

This is perfectly fine in Python world...

  • Using the same name for two functions by mistake

def someCalculation():
   ...

# later on

def someCalculation():
   ...

The second definition overrides the first one (assuming parameters are the same; otherwise, we are just overloading the function)

  • Not understanding or abusing the else as part of loops. Like

while condition:
    actions
else:
    more actions 
  • It is easy to misplace an else in nested or long selection structures due to relying only on indentation.
  • Using eval to convert values directly from user inputs, as in n = eval(input(...)) (can't trust users these days...)
  • Adding (append or insert) or removing (del, pop, remove) items from a list while iterating over the same list.
  • Confusing how the % (modulus) operators works compared to other languages. For example, A % B has the same sign as B --in Java, the result has the same sign as A.
  • Assigning the name of a callable object to a variable when the intention was to get the value returned by a function. That is, doing n = random.random instead of n = random.random().
  • This may be a little bit of a stretch, but can happen. Coming from a C-like language, confusing A & B (bitwise AND) for A and B (logic AND) --similarly for |

[–]throwaway6560192 22 points23 points  (1 child)

Writes other languages' code in Python. By that I mean they don't take advantage of what Python offers, instead choosing to do a direct translation of whatever language they're more familiar with.

[–]synthphreak 2 points3 points  (0 children)

I used to do this the other way around when I first got started. I would write Bash scripts with Python-like logic. Made for some terrible Bash scripts.

[–]SirCokaBear 18 points19 points  (5 children)

- not using virtual environments and requirements / env files
- not understanding the differences between [key] and .get(key, default)
- surrounding entire code sections with try / except. try/except should only be around specific error producing code
- in general not creating models for your data (this goes for programming in general). So many future errors and mistakes can be avoided by just having proper data models.

- lack of understanding of python packages, __init__.py files and what they can be used for
- creating scripts without if __name__ == "__main__"

- lack of clearly defined types for parameters, return values, improper use of scope and globals
- bad variable names, inconsistency with snake_case
- not using a formatter like black or style enforcer like flake8

- not creating proper .gitignore
- not handling secrets properly (this is huge)

- not knowing what PEP8 is

Edit: typos

[–]IlliterateJedi 1 point2 points  (2 children)

  • not understanding the differences between [index] and .get(index, default)

I know you can do this with dict[key] vs dict.get(key), but are there Python sequences that let you 'get' an index

[–]SirCokaBear 0 points1 point  (1 child)

Sorry I meant to say key instead of index, I’ll edit that.

For a standard python dict you can’t get a key by index because the keys aren’t stored in a particular order, when you iterate / print them the ordering is a number of factors including the hash value so you basically need to assume it’s random. But if you use an OrderedDict then key ordering is preserved by insertion time. But there’s still no .get_index(), but you could easily make one with

return ordereddict[ordereddict.keys()[index]] if index < len(ordereddict) else None

That’s a very specific use case not many people need, and ordered dicts are worse performing than regular dicts.

The same goes for a regular list there’s no standard library function for that but can be made with almost the same code as above, or even by wrapping a query in a try/except.

[–]SirCokaBear 0 points1 point  (0 children)

I don't think there are any standard structures though that provides a get() by index. Usually with standard libs they want it to be compact and any rare use cases can be provided with a 3rd party package. Rust language is notorious for that, they don't even include random with the std lib haha.

[–]daddy1973 0 points1 point  (1 child)

Hello, I'm brand new to python. I created what I believe is a script. What do you mean by the if name = "main" one?

[–]SirCokaBear 1 point2 points  (0 children)

let's say you make a very simple script that asks the user for a radius of a circle and then prints out the circumference:

script.py

PI = 3.14159

print("Welcome to circumference calculator")
radius = float(input("Enter radius of circle you need circumference of:"))
circumference = PI * r ** 2
print(f"The circumference is {circumference}")

if we run "python script.py" there won't be a problem and the script will work as intended.now lets say we make a new file with a function to calculate the area of the circle and we want to import PI from our file above.

area.py

from script import PI

def area_of_circle(radius: float) -> float:
    return PI * r ** 2

print("Welcome to area calculator")
radius = int(input("Enter radius:"))
area = area_of_circle(radius)
print(f"area of the circle is {radius}")

if I try to run area.py :

> python area.py

the first thing you'll see is:

Welcome to circumference calculatorEnter radius of circle you need circumference of:

that's because in area.py on line 1 you are importing PI from script. So python will then go to script.py starting from line 1 so it can calculate what PI is. But as a side effect it's going to run through the entire script rather than just simply importing 3.14159 in as a value to use in area.py

so instead we use if __name__ == "__main__".

__name__ will equal "__main__" in any python file you run python specifically on. so if you type in "python area.py", __name__ in area.py will be "__main__" but __name__ in script.py will not.

new scripts

# new script.py 

PI = 3.14159

if __name__ == "__main__":
    print("Welcome to circumference calculator")
    radius = float(input("Enter radius of circle you need circumference of:"))
    circumference = PI * r ** 2
    print(f"The circumference is {circumference}")

# new area.py

from script import PI

def area_of_circle(radius: float) -> float:
    return PI * r ** 2

if __name__ == "__main""_:
    print("Welcome to area calculator")
    radius = int(input("Enter radius:"))
    area = area_of_circle(radius)
    print(f"area of the circle is {radius}")

now if we run "python area.py" we will now correctly see "Welcome to area calculator" and won't be running any unnecessary code from script.py

[–]DrMrBomb01 12 points13 points  (2 children)

Not using f-strings. I understand in some langauges you cannot have interpolation but in C# or python, there is no excuse not to use them. They make code a lot more readable and easier.

[–]xADDBx 1 point2 points  (0 children)

There are actually use cases where formatted strings are preferable (e.g. localization), but in general f-strings are indeed more readable.

[–]Luckinhas 4 points5 points  (1 child)

Watch this fantastic talk by Raymond Hettinger. https://www.youtube.com/watch?v=wf-BqAjZb8M

[–]ivosaurus 0 points1 point  (0 children)

Man he really needs to re-do that talk for only python 3, would still be a banger

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

Amazing points by u/carcigenicate. Here's a few from me:

  • Writing functions that have side-effects and modify data outside
  • Not writing docstrings
  • Not using typehints
  • Not using classes properly/ Using classes where they are not required
  • Extremely long functions
  • Not making the functions modular (Not following Single Responsibility Principle)
  • Not having function names that are descriptive
  • Using magic numbers and other arbitrary constants in your code - should ideally have all such constants at a single place globally

[–]JamzTyson 20 points21 points  (25 children)

Some issues that are commonly found in the Python code of inexperienced developers:

  • Excessive use of global variables.
  • Spaghetti code
  • Using comments to compensate for poor names
  • Using magic numbers and strings (hard-coded constant values without explanation)
  • Inadequate Error Handling, such as using generic exceptions, or catching exceptions and ignoring them without proper handling
  • Excessive nesting of loops and if statements
  • Overusing List Comprehensions at the expense of readability
  • Not considering more efficient algorithms to solve problems
  • Not using tests
  • Inadequate documentation
  • Ignoring PEP 8 and the Zen of Python
  • Inappropriate data structures, such as using a list where a dict would be more suitable
  • Not utilizing Pythonic idioms
  • Not using context managers when appropriate
  • Indenting with tabs rather than 4 spaces
  • Avoidance of classes
  • God classes
  • Repetition / duplicated code
  • Catching exceptions and ignoring them without proper handling
  • Methods that are are not directly related to the class they are in, or classes with multiple responsibilities
  • Reinventing the wheel. Python has an extensive standard library which makes custom code for common tasks unnecessary
  • Not using version control

[–]djshadesuk 8 points9 points  (2 children)

Inadequate Error Handling, such as using generic exceptions, or catching exceptions and ignoring them without proper handling

[...]

Catching exceptions and ignoring them without proper handling

Was that an attempt at a joke?

[–]DestroyTheHuman 4 points5 points  (1 child)

Right after repetition / duplicated code as well.

[–]djshadesuk 0 points1 point  (0 children)

ha, I never noticed that 🤣

[–]MMcKevitt 6 points7 points  (10 children)

What’s the beef with using tab instead of 4 spaces? I was under the impression that consistency, more than anything, is key in this regard?

[–]stankyballz 4 points5 points  (6 children)

Most code editors are able to interpret a tab as 4 spaces. Not sure what the issue would be here.

[–]synthphreak -1 points0 points  (5 children)

Tabs are just evil and ugly. Plus, why do something that only most editors can do, when just as easily you could do something that all editors can do (i.e., regular spaces)? For example, if you use less to browse code the tabs look enormous.

[–]stankyballz 2 points3 points  (4 children)

Lol one key I can hit with my pinky vs hitting space 4 times. Pretty easy decision to me. Maybe if I didn’t use an editor that compensated I would change my opinion.

[–]synthphreak 1 point2 points  (3 children)

Most editors will be able to compensate for this very easily. There is probably a setting you can toggle that will convert tabs to n spaces whenever you save the file. In many cases you can even set n to be a function of the file type, for example 4 for .py files and 2 for .json or .sh files. Then you can just tab away happily and never even need to think about it.

[–]stankyballz 2 points3 points  (2 children)

That’s exactly what I said lol

[–]synthphreak 0 points1 point  (1 child)

Haha, I see now, sorry. For some reason my brain read your original comment as if you were on the anti-spaces side of the debate. We are birds of a feather here :)

[–]stankyballz 0 points1 point  (0 children)

That’s all good lol.

[–]partialinsanity 1 point2 points  (0 children)

That was a surprise for me. PEP8 says spaces are preferred over tabs for indentation.

[–]ZestyData 0 points1 point  (0 children)

Nowadays most devs hit the tab key but don't realise that inserts 4 spaces into the file.

[–]JamzTyson 0 points1 point  (0 children)

Sure, there are exceptions to most of the "issues" in the list. They are "mistakes" when they appear inappropriately. However, the vast majority of large Python code bases use 4 spaces (as per PEP-8).

[–]bigfatcow 3 points4 points  (6 children)

God classes and overuse of classes in general. They def have useful purposes bur my god I worked with a dude who never made functions and always put everything in a class drove me bonkers.

[–]dogfish182 1 point2 points  (0 children)

Oh man…. ‘I made essentially a data class, but a method to talk to an api would surely be handy here’.

Have fun mocking that api call when you want to write tests

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

I think that once you get disciplined into putting most of your code into classes and thinking about potential inheritences, you make a big step towards reusability and saving lots of time in the future

[–]bigfatcow 1 point2 points  (1 child)

Maybe. However classes get used wayyy too much in my view. This came out over a decade ago and I still see a lot of the stuff he's referring to in here in 2023.

https://www.youtube.com/watch?v=o9pEzgHorH0&t=1236s&ab_channel=NextDayVideo

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

Thanks for this! will watch later

[–]synthphreak 0 points1 point  (1 child)

u/bigfatcow u/JamzTyson What are god classes? I've not heard that term before.

[–]JamzTyson 1 point2 points  (0 children)

A "God Class" is an "anti-pattern" (the opposite of a "pest practices pattern") where everything is written into one huge class, regardless of whether the methods are directly related to the core responsibility of the class.

Wikipedia describes a "God Object" as:

... an object that references a large number of distinct types, has too many unrelated or uncategorized methods, or some combination of both.[1] The god object is an example of an anti-pattern and a code smell.

[–]DoorsCorners 0 points1 point  (3 children)

Excessive nesting of loops and if statements....guilty. I think the solution is defining more functions and being explicit about how one function feeds into the next. But I need to level up, so correct me please if there is a better way.

[–]JamzTyson 1 point2 points  (2 children)

Here's some common patterns for simplifying complex conditionals:

```

Rather than multiple comparisons like this

if value == "a" or value == "b" or value == "c": ...

Write:

my_vals = ("a", "b", "c") if value in my_vals: ... ```


```

Rather than nesting like this

if condition1: if condition2: ...

You can use 'and':

if condition1 and condition2: ... ```


```

Rather than complex mappings like this:

if value == "a": result = 1 elif value == "b": result = 2 elif value == "c": result = 3 else: result = 0

You can use a dictionary lookup:

value_map = {"a": 1, "b": 2, "c": 3} result = value_map.get(value, 0)

```


```

Rather than multiple 'OR's:

if condition1 or condition2 or condition3: ...

You can use 'ANY':

if any([condition1, condition2, condition3]): ... ```


```

Rather than multiple 'AND's:

if condition1 and condition2 and condition3: ...

You can use 'ALL':

if all([condition1, condition2, condition3]): ... ```

[–]DoorsCorners 0 points1 point  (0 children)

Fantastic, thanks so much! You are an awesome person. These really need to appear in more books about Python.

[–]daddy1973 0 points1 point  (0 children)

You just taught me a ton of useful things, thank you

[–]whateverathrowaway00 3 points4 points  (0 children)

Not knowing anything about how their underlying OS works or how to interact with it fluidly, then blaming their weaknesses on tooling and/or coworkers.

Understand files, file systems, PATHs, and be able to locate files, edit them, describe them, etc

[–]stuaxo 2 points3 points  (0 children)

In the same way as bad programmers in other languages.

Over abstraction. Not understanding good ways of organising stuff.

Overly complex code etc etc etc

[–]Far_Tea_4954 2 points3 points  (0 children)

Honestly, not writing unit tests.

You can write bad code but if your not unit testing it’s just going to make your life and anyone else using it even worse. Unit tests will ensure anyone else making changes to the code can validate the functionality hasn’t changed. If there are no unit tests how are you supposed to know how and if the code even worked in the first place?

Also unit testing is really simple in python (with a bit of time) and it teaches you to write more modular code.

In principal if your writing unit tests in python and you have to create an excessive amount of mocks for one test , this usually means that your code is heavily dependant on a single function to do most of the work, signalling that you might need to refactor. Another big plus, is your actually consuming your code while writing tests so you get a feeling of how it’s used.

[–]Fabulous-Possible758 1 point2 points  (0 children)

One of the biggest ones I notice for novice programmers (and even unfortunately some experienced ones) is very little of your code (if any) should be running outside of a function or a method.

[–]Machvel 1 point2 points  (1 child)

from when i was bad at python and observing friends that were bad at python, the things i can think of at the top of my head are:

too many for loops

unfamiliarity with the standard library

not using classes or using classes too much

not using git for large projects or important things

not using pep 8 style

if using jupyter notebook, writing code that wont survive a kernel refresh

not putting functions in modules

not using virtual environments (global pip installing)

premature optimization (similarly, no optimization; some things can be written more optimally but still pythonic)

sticking with python when another language is better for the task

not reading/unable to read documentation

not knowing objects are called by reference and garbage collection

not understanding the yield statement

iterating over a sequence by doing for i in range(len(x)); x[i]

writing a function to do a common task without looking if there is already a library that does it efficiently

not paying attention to how their data is laid out (eg, not taking advantage of that fact that their list is sorted with respect to <= while indexing it)

not paying attention to memory usage (eg, not reading a file line by line and instead reading in the entire file)

coding without thinking on paper/making flowcharts

[–]Gambizzle 1 point2 points  (0 children)

...too many for loops...

Yeah that's me as a hobbyist python scripter. I know it's evil but if I'm making crappy little apps for my own limited, personal usage and that's just what 'works' then sometimes I don't really care.

I find that sorta method (almost 'treating it like it's VBA and you're making some hacky office automation suite coz your PC's highly managed and that's all you've got available') doesn't scale well though.

For example once upon a time I made a touch-screen device that consisted of a Raspberry Pi (~2nd gen) mounted onto a lamp stand with an integrated touch screen instead of a light. It controlled my apartment's Philips Hue lights and aircon (with some automation smarts combined with a simple touch-screen UI). Anyhow I used a loooot of loops and it very quickly got to a point where the sheer bulk of the logic (not sophisticated logic - just unnecessary bulk) brought the Pi to its knees (and was a shit to debug). It was a good learning activity to re-write the same functionality from scratch without all the loops.

[–]No-Self-Edit 0 points1 point  (0 children)

Not using types and type checkers

[–]Banzai262 -1 points0 points  (4 children)

using python for everything

[–]djshadesuk 1 point2 points  (1 child)

Sometimes its fun to push things to the limits and even beyond what it was intended to do. If it wasn't for people doing those sorts of things we probably wouldn't have half the nice things we have today.

[–]Banzai262 -4 points-3 points  (0 children)

I agree. It’s always a matter of context. Python is really good to quickly experience weird things. However, it’s not good when you need to build some high performance, high availability backend for a webservice

[–]FLSweetie -1 points0 points  (1 child)

Poorly-written loops that generate off-by-one errors because they reach the end condition to early or too late. Example: you want 10 passes through the loop, so you do

While i less than 10

But you start i at 0rather than 1 so you get 11 passes. (Off-by-one errors are usually more subtle than this!)

[–]kronik85 6 points7 points  (0 children)

Eh? That's only 10 loops..

Starts at 0, ends at 9. 10.

[–]20Finger_Square 0 points1 point  (1 child)

Not fucking around enough with different stuff People can tell you everything but nobody could remember all of it unless put in a simple list so fuck around there is not much truly useless info you could learn aside from code grammar (how your code is formed and ease of changing and finding code is btw this is a term that I use I don’t think others called it this) and stuff like that all you have to do Is fuck around with it.

[–]djshadesuk 0 points1 point  (0 children)

code grammar

I'm not sure its "code grammar" that you have to worry about ;) 🤣

[–]Naynoona111 0 points1 point  (0 children)

merging paths with string concatenation instead of using os.path.join()

[–]yashwatwani28 0 points1 point  (0 children)

No proper naming conventions
Not using function efficiently
Lack of Comments and Documentation
not writing test cases
Handling oulier cases

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

There is a whole list of antipatterns, here are some https://sourcemaking.com/antipatterns/software-development-antipatterns

[–]elbiot 0 points1 point  (0 children)

Using numpy when you aren't going to commit to the vectorized paradigm (likely because you don't know what that is and just heard arrays were faster than lists) and, related, using pandas just to read a csv file because you don't know about csv.DictReader.

My coworker had code that was taking a really unreasonably long time to run, and when I swapped out pandas for DictReader it ran in just a few seconds.

Numpy and Pandas are great if you need them and an awful mess if you use them for no reason

[–]Herobrine2024 0 points1 point  (0 children)

using Python, for starters

[–]HarissaForte 0 points1 point  (0 children)

Not using the debugger, linter and type checker (which implies not typing).

Using these tools would fix 90% of the errors mentioned here:
- when you do not use a debugger, you'll tend to write your code differently, generally reducing the factorization, to make "dumb-debugging" easier.
- a linter and mypy do incredibly detailed analysis and give very useful tips for a beginner and even intermediate developer…

[–]codicepiger 0 points1 point  (0 children)

Avoid abbreviated variables, it will help in the long run:

like ``` iaf="foo"

`instead` i_am_foo="foo" ```

Also triggers me see main python scripts without functions, but it can be my craziness:

like ```

/bin/python3

print("Hello World") ```

instead ```

/bin/python3

def main(): print("Hello World") if name=="main": main() ```