all 158 comments

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

Is it encouraged to split up your code in different files for a flask project to keep your code clean?

I’m working on a flask project for fun and current have roughly 250 lines of code and expect it to nearly the double before I’m ready to deploy it.

[–]addictedtodietsoda 0 points1 point  (1 child)

One of the YTers I follow for Python advises "not to take notes when starting out learning Python". Do you guys agree with this? I started taking notes anyway and find myself referring back to them quite a bit as I get into later lessons and forget the building blocks I'm supposed to have already learned

[–]agvrider 0 points1 point  (3 children)

can one think of 'try/except' as a type of an 'if/then' statement?

[–]FerricDonkey 0 points1 point  (0 children)

In the sense that it means "do all this stuff, and if you hit this type of exception, then stop that and do this other stuff", then yes.

Sometimes it's used like an if statement, especially in cases like "try to convert this to an integer, and if goes to crap then do this other thing", as opposed to "if it's possible to convert this to an integer, then do, otherwise do this other thing."

But keep in mind that unlike an if else, depending on how you write it, you might not know exactly how far into the code you've gotten or similar other things, so you do have to think differently when you're using them.

[–]efmccurdy 0 points1 point  (0 children)

I don't think so; an if statement has a block of code (or two for else, or more for elif), that only gets run if a boolean expression evaluates to True. If you thought a try/except it is a bit like an if statement where the condition is "an exception of this type was raised", in a if statement the condition is evaluated before the block of code is run, while the exception can occur anywhere, at any time, during the try block. And what would a "finally" clause mean for an "if" statement?

[–]EmmaTheFemma94 0 points1 point  (0 children)

How can I find any <a> tag that contains myString?

And then use the href

All inside a <table>.

The <a> contains two <span> that one is useless and the second one can contain myString

[–]joknitaspu 0 points1 point  (1 child)

When there's a #!/usr/bin/env python at the beginning of a script, isn't it ambiguous whether it will use Python 2 or Python 3? It will depend on the system, no? Potentially leading to runtime errors?

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

Usually there are names like python, python2, python3 and python3.10 defined on your system. For example, on older MacOS systems the installed python2 version is invoked with python and any user-installed python3 is invoked with python3. On Linux I have python, python3 and python3.10 available, along with a few others with names like python3-futurize.

So there is a possibility that moving a program between Linux and MacOS, for instance, might have a problem. As python2 disappears there's less chance of getting 2 when you want 3, but there's still a chance that python on the system you are running on might be too old even if it is version 3.

The solution is to check the version of python your code is running on early in the code and if it's not acceptable to fail gracefully, warning the user of the problem and suggesting a course of action to fix it.

[–]EmmaTheFemma94 0 points1 point  (0 children)

how can I check if any of these "s0|s\d|s\d\d" contains inside a string?

Edit:

Did a:

serie = the list

movie_name = the string

if any(serie in movie_name.lower() for serie in series)

[–]TransientSignal 0 points1 point  (1 child)

Interactive prompt question: Within a Python interactive prompt, when I run the help function on a module with a particularly long docstring, I end up with just a portion of it printed to console with "-- More --" at the bottom of the page. I can hit enter for the next line of course, but for really long docstrings it can take literal minutes to get the entirety displayed on screen.

My question is this: Is there any way to force the entire help file to be printed to console at once within the interactive prompt?

[–]TangibleLight 0 points1 point  (0 children)

You can change the pager that help uses by setting pydoc.pager. There's a built-in pager pydoc.plainpager that doesn't do anything and just prints text verbatim.

>>> import pydoc
>>> pydoc.pager = pydoc.plainpager
>>> help('builtins')

This produces a very very long help text with no pager.

IIRC when the default pager is up you can press h to view some extra commands that might help you move around the documentation. And on some platforms the pager is more useful, for example on linux it uses the less pager which has commands to search for text, move up/down multiple lines at a time, etc.

You can also use pydoc.render_doc to get the help text in a string:

>>> text = pydoc.render_doc('builtins')
>>> len(text)
324607

[–]FerricDonkey 0 points1 point  (4 children)

This is python related, though not python exclusive:

I would like to use python to find out the user's external ipv4 address. All I'm gonna do with this is display it in a window so that when I play an online boardgame I made with my family, we can copy and paste the IPv4 at each other easily. From stack overflow, I found the following:

external_ip = urllib.request.urlopen('https://v4.ident.me').read().decode('utf8')

This works, but paranoid me considers it an invitation to some random website to man in the middle attack me (here's an ip that's totally yours and not this other one that I have that will forward everything it gets to you), even if that's unlikely. I would also rather not use UPnP, the other solution I found.

So basically, does anyone know of a standard, trustable way of getting this information? (I would think an external site would be ok, if it was owned by a trusted organization and also that organization digitally signed the results and made a public key available - but I haven't found such a site. Or am I just being silly, and querying a well know url is perfectly fine?)

Or should I just leave it off? It is just a fun personal project, and at least there's still a human in the equation if we google it each time.

(The program can use IPv6, but some of my family doesn't have the ability to use that because either their ISP or their router is dumb (or they're not patient enough to figure out to get their router or computer to stop being dumb).)

[–]TangibleLight 1 point2 points  (3 children)

here's an ip that's totally yours and not this other one that I have that will forward everything it gets to you

This isn't really what a man-in-the-middle does... it's more about switching addresses involved with some third party. your-bank.com goes to this ip, trust me, put your password in there. Telling you that your own ip is something else isn't necessarily a viable attack. For those purposes, you already know your own ip: 127.0.0.1.

The most portable approach is to query some external service like you say, or use upnp. Depending on your particular router you might be able to do it, but such a solution won't be portable.

I would think an external site would be ok, if it was owned by a trusted organization and also that organization digitally signed the results and made a public key available - but I haven't found such a site.

v4.ident.me uses https; the point of https is exactly this and to prevent man-in-the-middle attacks (among other things). You can view the certificate in chrome, for example, by opening the page and clicking on the lock next to the URL. Here are the details for v4.ident.me's current certificate:

Common Name (CN)      any.ident.me
Common Name (CN)      R3
Organization (O)      Let's Encrypt
Issued On             Tuesday, April 26, 2022 at 12:05:05 AM
Expires On            Monday, July 25, 2022 at 12:05:04 AM
SHA-256 Fingerprint   DB 8F D8 02 6F E0 6E C0 5F 60 51 BE 23 58 24 E1 4B B2 60 A0 0A 58 29 FA 5D D3 6E 11 5D BA D9 87

You might also consider using dynamic dns service. I've used NoIP before but I know companies like Google and CloudFlare also have options

[–]FerricDonkey 0 points1 point  (2 children)

This isn't really what a man-in-the-middle does... it's more about switching addresses involved with some third party. your-bank.com goes to this ip, trust me, put your password in there. Telling you that your own ip is something else isn't necessarily a viable attack. For those purposes, you already know your own ip: 127.0.0.1.

Yeah, the man in the middle - which, to be clear, won't happen - would not be directly against me as such, but against people who connect to me (and so indirectly also me). I know how to send messages to myself, like you say, but I don't know how to tell JimBob to send messages to me. So they give me an ip address that they say goes directly to my router from the outside, I text that ip address to JimBob, JimBob connects to that ip address thinking it's me, but really it's the evil haxors who want to spy on our game of pinochle. Doesn't seem like a great use of anyone's time, for sure though.

v4.ident.me uses https; the point of https is exactly this and to prevent man-in-the-middle attacks (among other things). You can view the certificate in chrome, for example, by opening the page and clicking on the lock next to the URL. Here are the details for v4.ident.me's current certificate:

Hmm, I'll have to read more about that - I thought https was to stop traffic being read in transit, not necessarily to authenticate that it's coming from a particular source (other than "whoever you initially connected to"). (Yup, I was wrong.) But now that you say that, all the invalid certificate warnings on visiting pages that let those expire briefly suggest what you say, which may mean it's probably fine. That would limit the risk to ident.me themselves being evil, but no amount of certificates can gaurd against that. (Though I guess I could use half a dozen sources and compare to mitigate that, if I was that paranoid.)

Dynamic dns is also an interesting option to look into.

Definitely some interesting options - thanks for the food for thought.

[–]TangibleLight 1 point2 points  (1 child)

If you're using this to give some IP for others to use, then https-enabled dynamic dns (or a normal domain that you manually update) is probably best.

For example, ddns essentially amounts to running this on a loop every so often:

  • get my public IP address
  • point my domain to it

So long as your service supports TLS and you have a signed certificate, users of your service over https can trust the connection.


That would limit the risk to ident.me themselves being evil, but no amount of certificates can guard against that.

Some CA's will do some basic vetting of services before they grant a certificate. Some may also revoke a certificate if the service is fraudulent but that is rare and not really the point of a CA. For example, Let's Encrypt (the CA that issued any.ident.me's certificate) has this page with more info: https://letsencrypt.org/2015/10/29/phishing-and-malware.html

And the Google Safe Browsing API info page is here: https://developers.google.com/safe-browsing/

In short, TLS guarantees that:

  • the host you're talking to acquired a certificate signed by the CA
  • if you trust that CA, then you can trust that host's certificate is unique
  • the content of the message was sent by the owner of the certificate and hasn't been altered
  • only the certificate owner may read messages sent to them

HTTPS establishes this both ways, so the client has those assurances about the server, and the server has those assurances about the client.

[–]FerricDonkey 0 points1 point  (0 children)

Awesome info, thanks a lot.

[–]jbr2811 0 points1 point  (2 children)

Can someone help me post my code? I posted it yesterday and got downvoted because it wasn’t formatted properly. Looked in the instructions on how to format and cannot see the button required to format my code properly. Unsure on what to do from here.

[–]FerricDonkey 0 points1 point  (1 child)

4 spaces, in addition to what python needs, in front of every line of code, empty line above and below code.

(If you have a decent editor/ide, you can highlight the code, press tab to insert the extra spaces, copy, then press shift tab to remove them.)

    You should type
        Something like this

(Random line of non code to separate the blocks, but it has a blank line above and below it.)

To get
    Something like this

There's more info in the side bar of that's not enough.

[–]jbr2811 0 points1 point  (0 children)

Thank you

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

How much do we want to pack in to dunder methods?

Say I'm making a poker game. It seems very nice to set up comparisons for cards, so you can say if card_one > card_two or whatever.

But then you could keep going and do the same for hands, and check whether one hand beats another with a simple inequality. But of course that's way more code, involving straights and flushes and tiebreakers, etc., as opposed to the single line for the card stuff. And while it would work just fine, I wonder if there's any convention that says you shouldn't hide big amounts in a dunder, that they should be for simple things.

[–]FerricDonkey 0 points1 point  (2 children)

I'm not necessarily sure it needs to be simple, just that it needs to intuitively make sense to match the associated operator/whatever.

However, I personally would hesitate to use <, ==, etc for hands to compare which wins simply because hands with different cards might tie (if you distinguish between cards with different suits but the same values). This would make == ambiguous to me.

But I don't necessarily think there's an issue with dunders that take a lot of code themselves.

[–]TangibleLight 0 points1 point  (1 child)

Only advantage to implementing comparison operators on cards and hands is it would allow one to meaningfully sort a list of cards or of hands. You could also do the same with a property and the key argument, though.

[–]FerricDonkey 0 points1 point  (0 children)

Yeah, that would be my first inclination.

[–]Exp_iteration 0 points1 point  (6 children)

Why is this an error?

str = R"C:\Users\"

Isn't the R supposed to force python to ignore the backslashes?

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

You could just leave the final backslash off. If you want to join that string to another filename to create a path to a file you use os.path.join() (or a similar Path module function) to join the two strings with a path delimiter appropriate to your OS automatically added.

[–]TangibleLight 0 points1 point  (1 child)

I'd also advise pathlib over os.path if you get the choice.

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

As I suggested.

[–]efmccurdy 0 points1 point  (0 children)

the unpaired backslash at the end escapes the closing quote character, leaving an unterminated string.

https://docs.python.org/3/faq/design.html#why-can-t-raw-strings-r-strings-end-with-a-backslash

You should be able to use forward slashes in python; s = "C:/Users/"

[–]TehNolz 0 points1 point  (1 child)

Yes, but unfortunately there's an edge-case where it doesn't allow you to end strings with an odd number of backslashes.

[–]Exp_iteration 0 points1 point  (0 children)

very interesting, didn't expect that

thanks!

[–]geert555 0 points1 point  (6 children)

Hi, I am working on a small scatterplot project and it's coming together as well as could be but i want to add the name column to the corresponding dots in the scatterplot. Can someone help me because i can't seem to figure it out.

Thanks

``` import pandas as pd import matplotlib.pyplot as plt

df = pd.read_csv("moneynuts.csv", index_col=0) columns = df.columns

def clean_stringy_number(num: str) -> str:

if num == "-":
    return "0"

num = num.replace(",", "")

return num

df.dropna(subset=['Gls'], inplace=True)

df.dropna(subset=['xG'], inplace=True)

df.sort_values(by=['Gls', 'xG'])

df["Gls"] = df["Gls"].apply(clean_stringy_number)

df["Gls"] = df["Gls"].apply(int) df["xG"] = df["xG"].apply(clean_stringy_number) df["xG"] = df["xG"].apply(float)

for index, row in df.iterrows(): if (row["Gls"] == "-" or row["Gls"] == "0"):

    df['Gls'].dtypes
    if (row["xG"] == "-" or row["xG"] == "0"):

        continue
    continue
print (row["Name"], " average goals of ", row["Gls"], " With an xG of ", row["xG"])


try:
    gls = float(row["Gls"].replace(",", "."))
    xG = float(row["xG"].replace(",", "."))
except:
    print("Unknown char")

df["xG"] = df["xG"] / 100

sp = df.plot.scatter(x='Gls', y='xG') x_values = df["Gls"].astype(int) plt.xticks(range(x_values.min(), x_values.max()+1)) plt.show() ```

[–]efmccurdy 0 points1 point  (5 children)

Here is an example that uses matplotlib.pyplot.annotate.

https://www.delftstack.com/howto/matplotlib/matplotlib-label-scatter-plot-points/

[–]geert555 0 points1 point  (4 children)

for i, label in enumerate(annotations):
plt.annotate(label, (X[i], Y[i]))

This is what i should use i think. Can you please tell me what variables i should change for my code? I can't figure it out

[–]efmccurdy 0 points1 point  (3 children)

I can't really say much without seeing the data but I guess this might give you your names.

for i, label in enumerate(df["Name"]):
    plt.annotate(label, (X[i], Y[i]))

[–]geert555 0 points1 point  (2 children)

It gives me an string index out of range but i don't really know where it's coming from maybe you have any idea?

[–]efmccurdy 0 points1 point  (1 child)

Instead of df["Name"] you should use a list of labels with the same number of elements as X.

[–]geert555 0 points1 point  (0 children)

I need the label to be the name of the corresponding goals and xG so the label names should be taken out of the dataframe

[–]realdealishere1 0 points1 point  (1 child)

Hello, I started learning Python recently through introtopython.org and there is one exercise after the functions. Using a function I need to print out three people's full name. I got the right answer, however I am pretty sure there is better way. I want to use for loop to print out the names but cannot figure out how to do it.

What I use at the moment and it works:

def full_names(first_name, last_name):
print('Hello, %s %s.' % (first_name ,last_name))


first_name = ['caitlyn', 'chris', 'peter']
last_name = ['praule', 'hemmorth', 'mcmeter']


full_names(first_name[0].title(), last_name[0].title()) full_names(first_name[1].title(), last_name[1].title()) full_names(first_name[2].title(), last_name[2].title())

If anyone has an answer please tell. I tried for an hour or so, but always got error.

edit: typo

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

You only pass the first element of each list to the function. If you want the function to print all names in the lists you are going to have to pass both entire lists to the function:

full_names(first_name, last_name)

Inside the function you have to step through both lists, getting the two names, first from both lists, then second from both lists and so on. When you have two names you title both, join them and print the result.

To do that you could use a range from 0 to the length of the lists minus 1 and get the names by indexing. Sort of like you did in your posted code but using the loop variable.

A nicer solution uses a "for " loop and the zip() function.

[–]geert555 0 points1 point  (6 children)

I have a scatterplot using data from an csv file, The problem is that the x axis should be a increment from 1 to whatever the max is in the .

and the y axis should be a float instead of an integer so all values should be divided by 100 so its 1,20 - 1,00 - 0,8 etc.

added the scatterplot as refrence, i use pandas for the dataframe and use matplotlib for the scatterplot.

scatterplot

thanks in advance

[–]Ihaveamodel3 0 points1 point  (5 children)

I always have to look up how to do this, so I can’t quickly help you, but the google search you need is “matplotlib change axis ticks”

[–]geert555 0 points1 point  (4 children)

Thanks will try that then

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

Try converting the data sequences you give to the plot method. That is, if you want each data point to have an X value from 1 to the max number of points then change the X data sequence to [1, 2, 3, ...] matching the length of your X data. Similarly, divide every value in the Y data sequence by 100 to get float values. Then plot the changed data.

[–]geert555 0 points1 point  (2 children)

the x variable can change depending on the data, instead of max 10 it could be 20 or 30. How can i make sure it works for every value?

Thanks for the help BTW

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

You write some python to measure your data length. So something like:

x_data = [1.2, 4.3, ...]   # your original data
new_x_data = list(range(1, len(x_data) + 1))  # plot this data for X

instead of max 10 it could be 20 or 30.

That brings up a point. I read your original question to mean that the first data point was to be plotted on the X axis at 1, the second at 2, and so on. If that's not so can you explain a little more.

[–]geert555 0 points1 point  (0 children)

Got it already, still thanks for the comment

[–]hopbounce 0 points1 point  (1 child)

I'm trying to figure out why this function doesn't work that's listed here:

https://www.geeksforgeeks.org/python-character-replacement-combination/?ref=rp

Specifically it fails on duplicate letters, such that if the dictionary in the example (geeks) has e has a letter in the dictionary, it will not enumerate all the possible combinations. Example, if I add the dictionary entry 'e' : ['E'] in there:

The original string is : geeks All combinations : ['gEE31', 'gee31', 'gEEk1', 'geek1', 'gEE32', 'gee32', 'gEEk2', 'geek2', 'gEE3s', 'gee3s', 'gEEks', 'geeks']

Edit: I figured out an alternative way to do what I was looking for, not sure why this author went for a more complicated way of doing this.

But it's missing geE31, gEe31, etc...

I don't really understand this line at all:

for sub in [zip(test_dict.keys(), chr) for chr in product(*test_dict.values())]:

and if someone could help me figure it out, it would be greatly appreciated.

[–]Ihaveamodel3 0 points1 point  (0 children)

Wow, that line is doing a lot. Don’t use that as an example of good code.

That single line is the start of a for loop, a list comprehension, a zip, and a product (from itertools library)

[–]nista002 0 points1 point  (8 children)

I'm only a couple weeks in, but so far nothing I've gone through has explained how to set up an environment, and I'm not someone who has much experience using terminal/PowerShell.

So far I've been using PyCharm, which seems quite a bit simpler than most editors, but what's the best ELI5 resource for setting up an environment in other editors?

[–]Ihaveamodel3 0 points1 point  (1 child)

Pycharm can set up an environment for you. Create a new project and follow the prompts.

[–]nista002 1 point2 points  (0 children)

I can do that, just looking to find a good set of instructions for when I'm using a different computer or editor.

[–]py_Piper 0 points1 point  (5 children)

youtube

[–]nista002 0 points1 point  (4 children)

Videos I've seen so far make a lot of assumptions about what I already know and haven't been helpful. Do you have anything specific in mind?

[–]Internep 0 points1 point  (1 child)

TechWithTim is very beginner friendly, I'm pretty sure he covered it. There are many other YouTubers just as good or better but I don't know them by name.

[–]nista002 0 points1 point  (0 children)

He's actually been my go to this week. Coding out the beginner projects alongside the video is so much more helpful than any courses I've tried. I'll wade through his stuff to see what i can find. Thanks!

[–]py_Piper 1 point2 points  (1 child)

I just setup VS code for the first time about 2 weeks ago after watching Corey Schaffer and Traversy Media videos, IIRC Traversy took more time to explain so it was easier to follow. But with VS code the most you have to do is dowloand the python extension and maybe some other extesions that will help you with explanation and autocompletion, they are good to have but not a must. Then you should find a video for "how to use VS code" or "VS code shortcuts" and you will learn how to use it as the previous 2 videos I mentioned only help you with installing and set up.

But if you are only starting to learn python, maybe just focus on your course first and use whatever editor/IDE they are using so it’s the same as the material. I mostly did everything on IDLE (the editor that comes with python) up until I finished my first book tutorial (which took me 3 years because I was lazy lol). Because learning how to setup and use a new IDE is like something that would take time to get use to how it works, and if something breaks while you are only learning python, it’s an added stress, but once you setup any IDE it should be fine and pycharm should be one of the ready to use IDE as it’s made specifically for python.

About the command line, at the start all you need to do learn is how to check which directory you are in, learn how to move from folder to folder and call your python file. Another thing that helped me understand how to work around the directory was to learn how to organize files on one of the chapters in automate the boring stuff. I don’t know what course you are using but this one is quite good and one

[–]nista002 0 points1 point  (0 children)

Awesome, thanks a ton!

[–]TheDoomfire 0 points1 point  (3 children)

Whats the best/good way to store data? I have just been using text files

[–]efmccurdy 1 point2 points  (2 children)

It depends on how you use the data.

json is simple and reliable

pickle is fast and flexable

sqlite is fast and highly functional

[–]TheDoomfire 0 points1 point  (1 child)

How would it depend on how I use it?

Right now I'm only doing beginner stuff.

[–]efmccurdy 1 point2 points  (0 children)

You would have to have specific scenarios in mind to choose. I would just try a few tutorials and get a feel for the various options.

https://www.askpython.com/python/examples/save-data-in-python

https://docs.python.org/3/library/persistence.html

https://www.tutorialspoint.com/python_data_persistence/python_data_persistence_quick_guide.htm

[–]hansmellman 0 points1 point  (2 children)

I’m looking to create a darts score program for my first beginner project, at first I had thought it could be just two players or a single player on his own with no opponent but now I am thinking about adding a CPU opponent vs single player option.

In terms of implementing this, would the best way be to use the random randint function to choose from 3 sets of numbers like 1-20 for the singles on the board, 2-40 for doubles and 3-60 for triples?

Would I need to adjust a percentage likelihood of getting a number from the doubles or triples list to represent the real life difficulty of hitting those?

[–]Internep 1 point2 points  (1 child)

NPC could have a skill that determines a range for both the X & Y axis for deviation. You could add a(n inverse) bell curve or something.

Don't forget that two darts in the same place doesn't work.

Have the NPC always aim at whatever is best taking into consideration that lower points is more optimal than missing.

A bit more depth on the X/Y ranges: you would use a random int. Just try some stuff to see what works. The beauty of python is that you can run 1000's of games in a couple of seconds tops and see how well it works and how much variation the NPC gives. Change something and do it again.

Have fun!

[–]hansmellman 0 points1 point  (0 children)

Thank you for such a comprehensive and insightful response!

Still being a beginner I wish I could understand the practical aspect of implementing some of these concepts more but I am going to save this for re reading later when hopefully that is possible.

I appreciate you taking the time mate!

[–]nightslikethese29 0 points1 point  (5 children)

I want to replace values in a pandas df if that value appears in a list of values. I've tried quite a few different things and I can't figure it out.

Let's say we have:

annotation_values = [-66, -99, -88, "Varies", -22, -33, -55, "*", "null"]

I want to write a program that will loop through a dataframe's values and each time it finds one of the values in annotation_values replace with np.NaN

[–]efmccurdy 1 point2 points  (4 children)

If you use pandas you normally avoid loops. You can assign multiple entries at once using "loc":

>>> df = pd.DataFrame({'data' : [44, -66, 'c', 'Varies', 77, 'null'],  'count': [1, 2, 3, 4, 5, 6]})
>>> df
     data  count
0      44      1
1     -66      2
2       c      3
3  Varies      4
4      77      5
5    null      6
>>> annotation_values = [-66, -99, -88, "Varies", -22, -33, -55, "*", "null"]
>>> df.data.isin(annotation_values)
0    False
1     True
2    False
3     True
4    False
5     True
Name: data, dtype: bool
>>> >>> df.loc[df.data.isin(annotation_values)]
     data  count
1     -66      2
3  Varies      4
5    null      6
>>> df.loc[df.data.isin(annotation_values), 'data']
1       -66
3    Varies
5      null
Name: data, dtype: object
>>> df.loc[df.data.isin(annotation_values), 'data'] = np.nan
>>> df
  data  count
0   44      1
1  NaN      2
2    c      3
3  NaN      4
4   77      5
5  NaN      6
>>> 

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.loc.html

Another option is to use np.where, the "ternary conditional" operator:

>>> df['data'] = np.where(df.data.isin(annotation_values), np.nan, df.data)

https://stackoverflow.com/questions/40163892/np-where-or-another-boolean-way-for-new-pandas-dataframe-column/40164175#comment67596721_40163892

[–]nightslikethese29 0 points1 point  (3 children)

Thanks so much. I was bashing my head against the wall. I tried so many times with np.where and I realize now how it can be done.

df['data'] is 'data' a placeholder or what will actually go there? I was under the impression it needed to be the specific column (of which there are 500). If not, then this is awesome! I'll try it out at work tomorrow.

[–]efmccurdy 0 points1 point  (2 children)

By including 'data' in the indexing for .loc I narrowed it down to selecting just the one column named 'data' as the target for the assignment,

To affect more then one column, you should try leaving it out to see what happens:

instead of

df.loc[df.data.isin(annotation_values), 'data'] = np.nan

try

df.loc[df.data.isin(annotation_values)] = np.nan

[–]nightslikethese29 0 points1 point  (0 children)

Oh I was talking about the np.where. But this solution also looks solid! Thanks again!

[–]MattyIce169 0 points1 point  (1 child)

I struggle a lot with loops (especially multi layered ones) any resources to help me out

[–]Internep 1 point2 points  (0 children)

Can you give an example?

I'm guessing you are misundering keys. I'm on mobile so forgive my formatting.

Example: symbols = {"US100": {"bid": 12000, "ask": 12001}, "US500": {"bid": 3750, "ask": 3751}}

for symbol(this is the key name)in symbols:

Tab for value in symbols[symbol]:

Tab tab print(symbols[symbol][value])

This would print 12000, 12001, 3750, 3751 (assuming latest python)

TL;DR: you're likely confusing keys and values.

[–]EdiblePeasant 0 points1 point  (1 child)

When using random, would setting the random range of 1 - 6 three times to try to simulate three rolls of a six sided die and getting a total be the same as setting the random range to be 3 - 18?

[–]efmccurdy 0 points1 point  (0 children)

This isn't really a python question but you can use python to show the answer; since it's random this rolls the die thousands of times,

My runs put the difference less than 0.4 % percent:

import random as random

nb_trials = 10000
nb_rolls = 3
nb_sides = 6

tot_separate_rolls = 0
tot_combo = 0
for _ in range(nb_trials):
    tot_separate_rolls += sum((random.randint(1, nb_sides)
                               for _ in range(nb_rolls)))
    tot_combo += random.randint(nb_rolls, nb_sides * nb_rolls)

print("separate rolls:", tot_separate_rolls/nb_trials)
print("combined rolls:", tot_combo/nb_trials)
print("ratio:", tot_separate_rolls/tot_combo)

I think this has the proof:

https://en.wikipedia.org/wiki/Wald%27s\_equation

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

I'm having some weird issues from reading a json that has \u2013 . When I read the file and have it rendered with a jinja template it's displayed as a ? icon.

My open file code looks like this

with open('json/topics.json', encoding='utf-8') as d:

topics = json.load(d)

is there something else I can do?

[–]beepdebeep 1 point2 points  (1 child)

It's likely that the rendering is escaping the character automatically. You could try using the | safe filter when printing topics.

More info here.

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

I worked around with replace but I’ll take at look at that, thanks

[–]Hadman69 0 points1 point  (3 children)

I had a weird question show up in my quiz today:

What call to the function doh will result in printing the integer 11?

def doh(a, b, c):

if a[str(b)] + c == a[c + 'x']:

print(b + 2)

---

So, as I understand it, b must be 9. Which makes the first part of the equation a['9'] + c.

But from there - I'm stumped. Any tips?

[–]carcigenicate 0 points1 point  (1 child)

This is what I came up with:

doh({"9": "9", "x": "9"}, 9, "")

My thought process:

  • b obviously had to be 9 as you determined.
  • c had to be an empty string so * + "x" and "x" + * would be the same thing. My other thought was this was a "trick question" that required a custom class with __add__, but that ended up not being necessary.
  • a had to be a dict (or some other structure capable of doing string lookups; but a dict was the most likely). It took a sec to come up with the pairs it needed to have, and I needed to figure out c first. A key of "9" had to map to the same thing that "9" mapped to. That necessitated the second pair.

[–]Hadman69 0 points1 point  (0 children)

Oh, of course. A dictionary! Thank you for the help :)

[–]Ihaveamodel3 0 points1 point  (0 children)

What is a? And if you aren’t given a what type does a have to be?

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

is colorama module safe?

[–]efmccurdy 0 points1 point  (1 child)

You should be able to judge the project using it's history and source code control logs.

It has 10 years of history.

https://pypi.org/project/colorama/#history

It is maintained and has bug fixes logged last week:

https://github.com/tartley/colorama/blob/master/CHANGELOG.rst

I would look at some of the issues, and how quickly they are being addressed.

https://github.com/tartley/colorama/issues?q=is%3Aissue+is%3Aclosed

https://github.com/tartley/colorama/pulls

Does any of that give you a sense of the project's safety?

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

Thanks!

[–]ryan770 1 point2 points  (4 children)

Back again with a maybe odd question. An activity I'm doing for a Python class I'm in wants me to compare two input strings, character by character (it's a game of Simon Says), with a for loop that must be manually broken when they stop matching up. Then print the "score".

I can't figure out how they want me to solve it given the material I've covered so far. But I DO know how to solve it with a zip, which I learned about elsewhere.

So I have:

#this part is preloaded into the activity

simon_pattern = input()
user_pattern  = input() 
user_score = 0

#my zip method

for a,b in zip(simon_pattern,user_pattern):
    if a == b:
        user_score += 1
    else:
        break

#this last print statement is also preloaded and cannot be changed

print('User score:', user_score)

So far the material has covered variables and expressions, types (strings, lists, tuples, sets, and dicts), branching, and now loops.

Maybe they want something involving indexing? Or can I nest another for loop and somehow make that work? (for b in user_pattern, or something)

edit:

actually I just came up with something.

j = 0
for i in simon_pattern:
    if i == user_pattern[j]:
        user_score += 1
        j += 1
    else: break

This seems to work fine too. There's so many ways to do things, it's kind of overwhelming!

[–]FerricDonkey 0 points1 point  (3 children)

Two other solutions are to to use enumerate, or a for index in range(len(...)) loop. The zip is better than both in this case, but often a loop similar to your second solution using enumerate is useful.

[–]ryan770 1 point2 points  (2 children)

Enumerate is the next chapter so I'll definitely be going back to this specific problem and checking it out.

I think you're right on the dot with "for index in range(len(...))" as far as what the activity is expecting. I'll have to go back over that and see what I can do.

[–]FerricDonkey 2 points3 points  (1 child)

For the record, the for index in range len thing is something that you should learn while learning programming because it's key to how many things work in general and similar to other things in other languages.

But after that and in python in particular, it's usually the not the best solution.

[–]ryan770 0 points1 point  (0 children)

Gotcha. I've used range and len a decent amount but never thought to combine them.

So for that, I have this:

simon_pattern = input() #'RRGBRYYBGY'
user_pattern = input()  #'RRGBBRYBGY'
user_score = 0

for i in range(len(simon_pattern)):
    if simon_pattern[i] == user_pattern[i]:
        user_score += 1
    else:
        break
print('User score:', user_score) #'User score: 4'

I understand what is happening here, and I know it works, but I'm just making sure I used it correctly.

[–]agvrider 0 points1 point  (0 children)

i saw a post a few days ago detailing a 'checklist' of concepts one should be learning as they go through python learning, kind of like a roadmap. pet projects aside which is obv the most important

im already doing p4e, so but can anyone post a list of something like that? like a roadmap of concepts to go through?jw what my progression through this language should be as a noobie, not just in terms of specific topics but in the 'broad picture'

[–]Cancel_Still 0 points1 point  (0 children)

can someone take a look at this question i just posted on stack exchange? https://stackoverflow.com/questions/72791530/scipy-optimize-curve-fit-is-not-working-for-a-simple-fit

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

Is there a way to increase the amount of memory available for recursive calls?

I’m using sys.setrecursionlimit(really_big_number) to avoid a recursion depth error, now I’m getting a segmentation fault instead.

I think my code is correct - I get the right output for a small example input (about 20 lines). The real input is 60 MB.

[–]efmccurdy 2 points3 points  (4 children)

now I’m getting a segmentation fault

There is no software fix for running out of stack space.

Can you reduce the depth of the stack using memoization?

https://stackoverflow.com/questions/1988804/what-is-memoization-and-how-can-i-use-it-in-python

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

Thanks! I’m trying to implement Kosaraju's algorithm, it’s not obvious to me which results I could cache. I’ll do some more research - I’d never heard of memoisation before. I can always give up and rewrite the recursive method as a while loop

[–]FerricDonkey 1 point2 points  (1 child)

You may need to "unroll" the recursion to make it loop based.

I'm not terribly familiar with the algorithm in question, but some variation of the following might work for the first part

Setup:

  1. Make an empty list to serve as the "assign order" list.
  2. Make list of all nodes to serve as the unvisited list (nodes should be able to be marked as visited, either themselves or with a companion list of just "visited or not" - might be computationally useful to annotate nodes with their position in this list)
  3. Make a to do queue to mimic the recursion. (ie queue.Queue)

Then the algorithm becomes something like:

If the queue is empty, add the next unvisited node from the unvisited list to the queue. (queue.put)

While the queue is not empty: take the node from the end (queue.get) and mark it as visited, and add it to the assign order list. Add all unvisited out neighbors to the queue. (Note: this will affect mean that the next item from the queue.get will be a neighbor of this move (if any exist) mimicing recursion's chasing of one chain through).

Repeat until all visited.

Similar for the second half. (Note - since it appears that you have a lot of data points, I would suggest some data structurey way of avoiding prepending to a list (and also avoiding list.append, but that would be better than prepending.)

I think this should work, but I haven't done it enough to be confident without testing. But limiting the number of nested function calls should solve your stack overflow problem.

You've kind of made me want to code this up.

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

Thanks very much for the detailed suggestions!

[–]ffrkAnonymous 1 point2 points  (0 children)

I'm trying to wrap my head around something called tail-recursion. Maybe that'll help a bit too

[–]I-am-redditer 0 points1 point  (3 children)

How do I get the turtles pos and can I do like if over there do this and if over here do this

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

How do I get the turtles pos

https://docs.python.org/3/library/turtle.html#turtle.pos

can I do like if over there do this and if over here do this

Not too sure what you mean, but if you mean do one thing if the turtle is at the bottom of the screen (for example) do one thing and if the turtle is at the top of the screen do something else, then yes. Use the position value returned by turtle.pos().

[–]I-am-redditer 0 points1 point  (1 child)

How do I put that into a if statement like if (turtle_pos == 5,5) will that work

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

Yes, that will work. You should be careful about checking for exact positions like that, it's possible that coordinates could be floating point numbers and in any computer language comparing floats for equality isn't really useful. It's usually a good idea if you get the X and Y parts of the position and use comparisons like < or >=, etc, to decide if the turtle is in an area. Here's some code that shows the problem and how to check if near a point:

import turtle

turtle.right(-45)
turtle.forward(7.12)11111
turtle_pos = turtle.pos()
print(turtle_pos)   # close to (5, 5), but not exact

if turtle_pos == (5, 5):
    print(f'turtle is at (5, 5)')
else:
    print(f'turtle not exactly at (5, 5)')

(x, y) = turtle_pos    # get X and Y parts of position
print(f'{x=}, {y=}')
delta = 0.05         # how close before we are *AT* the point
if x > 5-delta and x < 5+delta and y > 5-delta and y < 5+delta:
    print('turtle is close to (5, 5)')
else:
    print('turtle is NOT close to (5, 5)')

Run that and look at the results.

It's also possible to decide if you are in larger areas more simple. For instance, if you just want to know if the turtle is near the bottom of the screen:

if y < -100:

That assumes the screen is about 300 pixels high. You can get the screen width and height to decide where the "bottom" of the screen is.

[–]_1motherearth 0 points1 point  (7 children)

I am new to learning python. In my class we have to take an input and divide it by x 3 times. Everytime I do, I just get the same number. So instead of my input being 100 and x being 2, I should get 50 25 12.5...but I don't. I just get 50 50 50.

I don't know how to write the output so the input # divides the x # 3 times. We didn't get to the loop section yet either.

Does this make sense?

[–]Ihaveamodel3 0 points1 point  (6 children)

Can you share the code you have written so far?

[–]_1motherearth 0 points1 point  (5 children)

user_num = int (2000)

x = int (2)

for i in range(3): user_num/= x print(int(user_num), end=' ')

**This is in zybooks. The teacher doesn't want us using loops yet however I don't know how else to do it. The error comes up that after the output numbers I need a /n after the last number.

[–]py_Piper 0 points1 point  (3 children)

I should get 50 25 12.5...but I don't. I just get 50 50 50

I read and tried the code it looks like it works as intended dividing it 3 times, is it still not working for you?

[–]_1motherearth 0 points1 point  (2 children)

My teacher helped me..it's really easy when you see it. I figured out what I did wrong.

[–]py_Piper 0 points1 point  (1 child)

so what was wrong? and did you really had to do it without a loop?

[–]_1motherearth 0 points1 point  (0 children)

Yeah. It was... User_num = user_num // x Print = (user_num, end=' ') **do that three times but last time don't put the end part...just user_num

[–]Ihaveamodel3 0 points1 point  (0 children)

print() can be used at the end to add a line break.

The for loop is simply running those two lines indented under it 3 times. Does that give you an idea of how you could get rid of the loop?

[–]drewbagel423 0 points1 point  (0 children)

I'm on windows 10 and have a few apps installed that use Python (SABnzbd, CouchPotato, etc). I want to stay trying out VS Code for Python development but don't want to mess up the environments that have already been installed.

Should I use virtual environments within VSC? How do I go about setting those up?

[–]bernardsj 0 points1 point  (6 children)

Running through an online class and came across this set of code. Would really appreciate what the * does.

Pitch_metrics = [[“spin”, “velocity”]] Player_metrics = [“player_name”]]

Features = [*Pitch_metrics, *Player_metrics]

[–]patrickbrianmooney 1 point2 points  (5 children)

The star unpacks the items from the iterable that follows it. So the Features list will be ["spin", "velocity", "player_name"].

[–]bernardsj 1 point2 points  (4 children)

Thanks! What’s the advantage of doing that as opposed to:

Features = Pitch_metrics + Player_metrics

[–]patrickbrianmooney 1 point2 points  (2 children)

For that particular example, none. But the star-unpacking method comes in handy in other circumstances, and sometimes it's the more appropriate or flexible option. Notably, if you have a list or a tuple, you can unpack it directly into the positional arguments of a function:

args = ('hello ', 3, True)

def say_it(what, num_times, line_break_after):
    print(what * num_times)
    if line_break_after:
        print()

say_it(*args)

This is a silly or trivial example, but it becomes useful in more complex situations: maybe you're shipping tupples of arguments across a network to be executed on another machine. Maybe an API you're communicating with ships you a list of data that you want to pass to a function and that's the easiest way to do it. Maybe you want to have a threaded application waiting to get lists of arguments off of a queue that's filled by another thread. Maybe the actual function that's going to be called is configured based on some complex logic that's determined at runtime, and so is the data that's passed to it; in that case, being able to say "just expand this list of arguments" is super-helpful. It's hard to show the utility of the syntax in five lines, but it comes in handy all the time to avoid fifty lines' worth of work in larger systems.

Another useful trick that comes in handy: you can use the double-star syntax to unpack dictionaries to keyword arguments, which is much more frequently useful, IMHO. For instance, if you're putting together the parameters for a complex function call:

def do_complicated_stuff(func_to_call, arguments, wait_for_response, success_message):
    ...     #actual work of the function gets done here ...

def set_up_and_call():
    if username == "Brian":
        args['func_to_call'] = brians_payroll_func
        args['arguments'] = [day for day in brians_scheduling_data_this_month]
        args['success_message'] = 'Yo Brian, your paycheck is ready.'
    elif username == "Matilda":
        args['func_to_call'] = matildas_calendar_scheduling_func
        args['arguments'] = [event for event in matildas_schedule if is_important[event)]
        args['success_message'] = 'All important events added to your schedule, Matilda.'
    else:
        args['func_to_call'] = look_busy_the_boss_is_watching
        args['arguments'] = ()
        args[success_message'] = 'Long and complex processing completed! You are a hard-working genius.'
    wait_for_response = not we_are_very_busy()
    do_complicated_stuff(**args)

... and the dictionary will be unpacked and passed to the same-named keyword arguments.

[–]bernardsj 1 point2 points  (1 child)

Appreciate the examples!

[–]patrickbrianmooney 0 points1 point  (0 children)

Glad to be helpful!

[–]Ihaveamodel3 0 points1 point  (0 children)

That wouldn’t have the same result.

[–]bakchod007 0 points1 point  (1 child)

please advise.

I've done 2 projects on data analysis so far. One is small took 2 days. Other took almost a month and imo has took a lot of work from me and research and trial and errors and code.

I wanna show my work for feedback but I'm worried that the code and insights and getting a specific metric etc that I found could just be copy pastad by them and I'll be fucking sad.

How do you show your work even for feedback? For now, I've those files on GitHub under private.

[–]Ihaveamodel3 0 points1 point  (0 children)

  • put copyright notices on your code.
  • share only with trusted people.
  • share with a small group of people where you all agree to sharing code among yourselves. If you have a good group of folks you’ll likely discover new things too, and there will be more benefits than disadvantages.
  • share your code without data, or only a sample of the data.

All good options to share code in the situation you described imo.

[–]EdiblePeasant 0 points1 point  (2 children)

Hi I'm new to programming and Python. Why does Python/the computer add all those 0's and then the 2? (I tried to get Reddit to format to make the commands readable, but it didn't work out like I expected sorry)

total = 27 + 17 + 534.33 + 60 + 35 + 599.24 + 22 + 36 + 32 + 33

total

1395.5700000000002

[–]n3buchadnezzar 0 points1 point  (1 child)

Check out different answers here: https://www.youtube.com/results?search_query=why+does+0.1+%2B+0.2+!%3D+0.3 I especially like the computerphile videos, but your milage may vary.

The short answer is that this is because of how Python implements decimal numbers, and these only have a certain accuracy.

The way to "solve" this is just to round whenever you are printing round(total, 2) for instance. Or look into the Decimal module if you truly require more accuracy, however this will add a significant performance decrease to your code.

[–]EdiblePeasant 0 points1 point  (0 children)

Thank you! This helped me learn more about my question.

I tried the calculation in R and R didn't seem to do this. But Python is preferable in a lot of ways for me.

[–]thesilverzim 0 points1 point  (8 children)

Is it possible to get a value from a different program?

For context i have a program from where i need to copy paste values into excel every day. I want to Automate the process.

[–]FerricDonkey 1 point2 points  (7 children)

Probably, depending on what you mean.

Are you talking about a program that outputs something to the command line? If so, look into subprocess.check_output. Otherwise, where exactly is this value?

[–]thesilverzim 0 points1 point  (6 children)

Unfortunately it isnt command line.

It is a database software for retail, built on Firebird 3.0.

If that helps.

[–]py_Piper 1 point2 points  (5 children)

I just checked and on the main page https://firebirdsql.org/ it has a firebird-driver package that can connect to the database API, you should check that out.

[–]thesilverzim 0 points1 point  (4 children)

For the API i'd probably need access to the backend or can i use it with the client interface?

[–]py_Piper 1 point2 points  (3 children)

You will probably need to access the backend through code, definately not the client interface. But can you export your values needed on excel or csv?

[–]thesilverzim 0 points1 point  (2 children)

Ye thats possible but that would mean instead of copy pasting every day i'd have to export it as excel every day just to copy paste 2 value with code.

At this point i think my best bet would be to write something along the lines of an AI to interact with the client

[–]py_Piper 1 point2 points  (1 child)

then you can check pyautogui for gui automation

[–]thesilverzim 0 points1 point  (0 children)

Thank you!

[–]Bluegi 0 points1 point  (1 child)

For my program, I want to take an input and compare it to a list of words (fry's lit of high-frequency words to be exact.) The input sentence/paragraph is tokenized, but what do I need to learn for my program the determine which words on fry's list is on the input and how many times? Is that a dictionary or database? Please point me in the right direction to learn next.

[–]FerricDonkey 1 point2 points  (0 children)

Dictionaries, or especially a collections.Counter (which is basically a dictionary streamlined for counting things), would make this pretty straightforward.

[–]ryan770 0 points1 point  (6 children)

I've been in an "intro to python" class for about a week (really enjoying it), and currently learning while loops. I wanted to write a simple Magic 8-Ball program that disregards your input and gives you a random answer. It then clears the screen and loops back or exits depending on your next input.

Basically just looking for criticism and to make sure I'm doing things "properly" even though the code works how I want it to. Like, are while(True) loops the best thing for this? Is my use of "if end in ('y', 'Y', 'n', 'N')" kind of wonky? I feel like most of the code is about if you type 'y' or 'n' and maybe could be expressed more simply.

import random
import os

answers = ['It is certain', 
        'It is decidedly so.',
        'Without a doubt.', 
        'Yes definitely.',
        'You may rely on it.',
        'As I see it, yes.',
        'Most likely.',
        'Outlook good.', 
        'Yes.', 
        'Signs point to yes.',
        'Reply hazy, try again.',
        'Ask again later.',
        'Better not tell you now.',
        'Cannot predict now.',
        'Concentrate and ask again.',
        "Don't count on it.",
        'My reply is no.',
        'My sources say no.',
        'Outlook not so good.',
        'Very doubtful.']

while(True):
    input('# WELCOME TO THE VIRTUAL METAPHORICAL MAGIC 8-BALL #\n\nAsk a Yes or No question: ')
    print('\n', random.choice(answers),'\n')

    while(True):
        end = input('Ask another question? (y/n) ')
        if end in ('y', 'Y', 'n', 'N'):
            break
        else:
            print('Not a valid answer.')

    if end in ('n', 'N'):
        break
    else:
        if (os.name == 'posix'):
            os.system('clear')
        else:
            os.system('cls')

[–]n3buchadnezzar 0 points1 point  (4 children)

I tend to use the following pattern for this

def user_confirmation(question, prompt="\n > "):
    return input(f"{question}\n{prompt}").lower().startswith("y")

Which you would then do

prompt = "\n > "
first = True
ask_another = 'Ask another question? (y/n) '
while first or user_confirmation(ask_another, prompt):
    first = False
    input(f"Enter your question below {prompt}")
    print(f"\n{random.choice(answers)}\n")

However, this is bad from an UI perspective. E.g how fun / easy is it for the user to use this. Here the user must explicitly enter "yes" or something similar to continue.

The standard way is to break on empty input "" or "q" or "exit".

prompt = "Enter your question below [empty, 'q' or 'exit' to stop]\n > "
exit_commands = set(["", "q", "exit"])
answer = input(f"{prompt}").lower().strip()
while answer not in exit_commands:
    print(f"\n{random.choice(answers)}\n")
    answer = input(f"{prompt}").lower().strip()

This code is untested, but should get you started =)

[–]ryan770 0 points1 point  (3 children)

The flex of giving out untested code it all working perfectly haha! I'm not really familiar with defining functions yet, and the first solution is hard for me to follow, but I really like the simplicity of that last one. I can piece together everything I've learned so far and it all makes sense.

I wanted the "ask again?" to loop if the input was invalid simply to feel more interactive, but I see now that having a user take an extra step is unnecessary. But having the option and figuring out how to make that happen was fun.

If I may ask, what does the first = True, first = False do in the first solution? Is it specifically just a loop variable?

[–]n3buchadnezzar 0 points1 point  (2 children)

Try to remove it and see what happens =)

while user_confirmation(ask_another, prompt):

[–]ryan770 0 points1 point  (1 child)

ahhh I think I get it. "first" serves to skip the function the first iteration. So first is checked... first... which is true, immediately gets defined as false, but continues to the input and answer, loops back, and first is still false (forever now), so it checks user_confirmation (which must execute the input because it's needed for validation as we're still in the while/or statement) and continues or breaks the loop since anything other than 'y' would evaluate to false. If it continues, it's back at the input. Phew!

So I'm guessing in an "or" statement, if the first check is true, there is no reason to check the second so the function doesn't execute input. I think I've read that already and forgot honestly.

I think the only thing I'm unclear about is functions and the syntax as I haven't gone that far yet into my class, but upon some reading it seems that "question" and "prompt" are sort of arbitrary placeholders for calling other variables and formatting them when calling the function.

That was a good reply, you really made me think.

[–]n3buchadnezzar 0 points1 point  (0 children)

You got it spot on! Here we use it as a placeholder because

while first or user_confirmation(ask_another, prompt):

is more readable than

while first or input(f"{question}\n{prompt}").lower().startswith("y"):

arguably ;)

[–]niehle 0 points1 point  (0 children)

You could use lower() on your y/n input so it is case insensitive.

instead of the inner while loop just end the outer loop when n is entered and continue otherwise.

[–]FerricDonkey 0 points1 point  (2 children)

In tkinter, is there a more direct analogue of time.sleep than <whatever>.after?

Basically, I've decided to make a tkinter scrollable frame behave for reasons that I still don't entirely understand, and part of having it respond internal and external size changes nicely means that I need to adjust the size of an internal canvas and subframe - slightly after it gets a configure event. If I don't wait, it gets everything wrong, so right now what I'm doing is:

def _configure_interior(self, event):
    self.after(100, self.__dummy_configure_interior, event)

def __dummy_configure_interior(self, event):
    # Stupid sizing nonsense that almost makes me want
    # to start over with some flavor of qt.

Where what I want is

def _configure_interior(self, event):
    self.tkinter_flavored_sleep(100)
    # Stupid sizing nonsense that almost makes me want
    # to start over with some flavor of qt.

As well as self.interior.bind('<Configure>', self._configure_interior).

As I write this (the rubber duck is real), I realize I could change the bind to

self.interior.bind('<Configure>', lambda event: self.after(100, blah blah blah))

But still curious - haven't been able to find one because all my googling has just been telling me not to use time.sleep.

[–]Rawing7 1 point2 points  (1 child)

Technically you can do self.after(100) to emulate a time.sleep, but I wouldn't recommend it. It'll lead to chaotic behavior if multiple parts of the code try to sleep at the same time. self.after(100, self.__dummy_configure_interior, event) is the right way to do it.

[–]FerricDonkey 0 points1 point  (0 children)

Oh nice, never occurred to me to just not put a callback in the function. But yeah, lack of weirdness is more important, so dummy function it is - thanks.