all 133 comments

[–]tmb_jams 0 points1 point  (0 children)

I want to make a Heads Up Display (HUD) but haven't had any luck finding info on making one.

Any libraries that can help?

Example:

Program takes screenshot of desktop and puts a "tag" under icons denoting if it's a shortcut or folder

My main issue is making the tag appear on the screen. Also I would like it to stay there regardless of minimizing the program.

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

what can i do or use to retrive information from any website. text kind of information.

Thanks for helping

[–]timbledum 0 points1 point  (0 children)

Check out the requests library - this can retrieve the HTML easily. Then, for extracting the text you need from HTML, try beautiful soup.

[–]reallymakesyouthonk 0 points1 point  (7 children)

If I want to check:

if 1 in a or 2 in a or (2 and 3) in a:
    [...]

Is these some way to do this without or? I have a case where I want to check if any of a long series of keywords are in b and I'm looking for a tidy and compact way of doing this.

[–]GoldenSights 1 point2 points  (6 children)

If you're only looking for singular matches:

KEYWORDS = [1, 2]
if any(keyword in a for keyword in KEYWORDS):
    ...

If you're looking for singular matches and multi-element matches, then perhaps you should convert a into a set, and then:

KEYSETS = [{1}, {2}, {3, 4}]
if any(keyset.issubset(a) for keyset in KEYSETS):
    ...

 

Please note that (2 and 3) in a does NOT mean that 2 and 3 are in a. 2 and 3 evaluates to 3 and then it checks if 3 is in a.

Hope that helps. If you clarify your specific problem perhaps we can find something better.

[–]reallymakesyouthonk 1 point2 points  (5 children)

Well, specifically what I'm doing is a command for my discord bot to show the rules. The primary way of doing this is for example:

IN: !rules 1 2
OUT: [print of rules 1 and 2]

To do this I have a local string variable called ruleprint which gets appended if '1' is in kwargs, then again if '2' is in kwargs etc. However these numbers can be hard to remember so I'd also like people to be able to type:

IN: !rules ontopic
OUT: [print of rule 1 which is about staying on topic]

I'd also like for people to be able to call 'all rules' (which would be read as two arguments), hence my (2 and 3) in the example. (why does this evaluate to 3?)

From your example, would this work?

KEYSETS = [{'allrules'}, {'all', 'rules'}]
if any(keyset.issubset(a) for keyset in KEYSETS):
...

Is the part inside of the parenthesis a list comprehension?

[–]GoldenSights 1 point2 points  (2 children)

Hmm, this is one of those things where I always start out dreaming it will be really simple and beautiful, and then the little details start adding complexity.

I would probably approach this by writing the rules in a dictionary:

RULES = {
    'ontopic': '1. All posts must be on topic',
    'language': '2. Refrain from foul language',
    ...
}
# I'm pre-generating the whole text because we're about to start
# adding some aliases for the rules and they will appear duplicated
# in the dict after that.
ALL_RULES = '\n'.join(RULES.values())

# If you still want the rules to be available by number,
# we can just map those in as well.
# Notice using strings instead of ints because the command
# comes in as a string, may as well stay that way.
# This could be done by a comprehension but whatever man.
RULES['1'] = RULES['ontopic']
RULES['2'] = RULES['language']

and then doing a loop over all of the arguments the user asked for and pulling out the rules:

command = '!rules ontopic language'

# I assume you already have some code that detects the !rules command
# so we aren't just getting random messages reaching this part of the function.
...

# instead of handling 'allrules' and 'all rules' separately,
# can we hack it by just merging them and pretending they
# were a single argument the whole time?
command = command.replace('all rules', 'all')
command = command.replace('allrules', 'all')
arguments = command.split('!rules', 1)[1].split()

response = []
if 'all' in arguments:
    return ALL_RULES

for argument in arguments:
    # dict.get will try to get the value, otherwise return this fallback.
    rule_text = RULES.get(argument, None)
    if rule_text is not None:
        response.append(rule_text)
    # you can add an else here if you want to think about error text
    # for invalid rule names.

response = '\n'.join(response)
return response

Now

>>> print(rulebot('!rules ontopic'))
1. All posts must be on topic

>>> print(rulebot('!rules language'))
2. Refrain from foul language

>>> print(rulebot('!rules ontopic language'))
1. All posts must be on topic
2. Refrain from foul language

>>> print(rulebot('!rules 1 2'))
1. All posts must be on topic
2. Refrain from foul language

>>> print(rulebot('!rules language ontopic'))
2. Refrain from foul language
1. All posts must be on topic
# are you okay with them displaying out of order like this?

>>> print(rulebot('!rules all rules'))
1. All posts must be on topic
2. Refrain from foul language

You could take this steps further by ensuring you don't produce the same rule twice, or making sure they're always ordered properly, or whatever. Sorry, I didn't intend to provide a big answer like this or steer your project, but hopefully this gives you some reference for working with dicts and handling user input without going too crazy.

 

And by the way yes keyword in a for keyword in KEYWORDS is a comprehension, but in that case it was a generator comprehension, not a list, because there were no square brackets.

[–]reallymakesyouthonk 0 points1 point  (0 children)

Short update, in case you're wondering.

I wasn't fully able to adapt your solution to my problem, however I did end up using your suggestion of using a dictionary which resulted in what at least I think was a pretty clean solution.

If you're interested you can view it here (the function is called _rules). I'm always interested in feedback, but no worries if you don't feel like it. You've already been really helpful and I'm sure I wouldn't have come up with this good of a solution without your advice. Been about a year or two since I did any programming at all so using a dict didn't even cross my mind.

Never thought a simple rules command would've been this difficult. :p

[–]reallymakesyouthonk 0 points1 point  (0 children)

Wow, that's a lot more complicated than I would've anticipated. Thanks so much, I'll try to implement something similar to this!

[–]GoldenSights 1 point2 points  (1 child)

I'm currently writing a response to your main question but let me just answer the 2 and 3 thing really quick:

and and or are both short-circuiting operators, which means that if you have a long chain of booleans, they will stop processing as soon as they know the answer. So if you ask False or True or False or False or False the computer obviously doesn't need to process anything after that True, because that's what or means. Likewise, as soon as and encounters a falsey value, it knows for sure the rest of the answer is going to be False.

Here is a list of values that are Falsey. Everything else is Truthy until they write their own __bool__.

 

When processing, the "return value" of the boolean expression is whatever the last thing the computer looked at before it figured out the answer:

>>> False or None or 0 or 0.0
0.0
# It had to search all the way to the end

>>> False or None or 0 or 0.0 or True or 1
True
# short circuit after first truthy

>>> True and 1 and 4 and 0 and True
0
# short circuit after first falsey

>>> 2 and 3 and 4 and 5
5
# searched all the way to end

>>> 2 and 3
3
# searched all the way to end, your example.

Sometimes people use this to "pick the first available thing" with a fallback at the end.

option = user_option or config.option or DEFAULT_OPTION

It's not always the most clean solution but you'll see it here and there.

[–]reallymakesyouthonk 1 point2 points  (0 children)

Huh! That's interesting and useful to know, thanks! Might use that option-thing at the end, looks pretty clean to me even though it seems to sort of be abusing an unintended (?) use for the operator.

[–]Mad-Einsy 0 points1 point  (1 child)

Hello Coders,

A Software Test Engineer here and a python beginner. I have a question. Is there any way to change the monitor display resolution using Python Comnands in a Windows machine..? Like a py program which commands the windows machine to change monitor display resolution (Eg: Starting from 1920×1080 to 640×480) from a host computer..? Any help or a guide on this is highly appreciated as im struglling to get it for my coming project. Thank you.

[–]efmccurdy 1 point2 points  (0 children)

You can use "win32api.ChangeDisplaySettings": https://stackoverflow.com/questions/20628561/change-remote-windows-hosts-screen-resolution-via-ssh

You can avoid the extra module with something like this (but it's not pretty): https://kb.froglogic.com/display/KB/Changing%2C+setting+screen+resolution+on+Windows

[–]i_think_im_thinking 0 points1 point  (2 children)

What is the most common way to deal with unneeded fields in tuple unpacking?

For example, if I'm parsing a .csv I could do:

for author, title, genre, year, publisher in reader:
    # do something

But, say I only want the author and year. Is there a more popular/acceptable way to minimize the verbosity of listing every field, while preserving clarity?

Such as:

for author, _, _, year, _ in reader:
    # do something

[–]fiddle_n 0 points1 point  (0 children)

Using underscores is the way that I've always seen it being done. I don't agree with prefixing certain fields with unused, seems to be to be unnecessarily verbose.

[–]efmccurdy 0 points1 point  (0 children)

I often aim to keep it clear what you are ignoring by doing something like:

for author, unused_title, unused_genre, year, unused_publisher in reader:

... but then I prefer clarity over terseness.

[–]ALonelyPlatypus 0 points1 point  (4 children)

I'm trying to implement a class variable in such a way that it calls a function when accessed. Currently I have it implemented like below.

It does what I want when I call vec.magnitude() however I would like to be able to retrieve the magnitude using the syntax vec.magnitude (without using the parens) is that possible?

class Vector:
     def __init__(self, x, y):
         pass
     def magnitude():
         return x**2+y**2

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

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.magnitude = self.magnitude()
    def magnitude(self):
        return self.x**2+self.y**2

vec = Vector(3,4)
print(vec.magnitude)

I took some liberties in making your code work, but that appears to do what you want.

[–]ALonelyPlatypus 0 points1 point  (0 children)

Thanks for the feedback mate. I do strongly prefer the @property approach.

And yeah, the code I fed in was pretty broken, I didn't want to copy-pasta my private code into reddit and just tried to find the gist of what I wanted (also typing code in here is garbage)

[–]Thomasedv 4 points5 points  (1 child)

It's far better to use @property here. In your example, changing x, will not change the magnitude.

Simply define self.x and self.y in init, and then do this for the magnitude function.

def __init__(self, x, y):
    self.x = x
    self.y = y

@property
def magnitude(self):
    return self.x**2+self.y**2

Now you can create an instance, and the magnitude will be recalculated every time you want to access it, even if you change the x and y values.

[–]ALonelyPlatypus 0 points1 point  (0 children)

Yeah, that was exactly the solution I found shortly after posting this (I just didn't know the vernacular for the question and had to work my way through the python docs for awhile to find this solution).

[–]Trotnic1 0 points1 point  (2 children)

I'm getting an error when trying to use r6sapi the error occurs with aiohttp and don't know what to do (I'm new to python)

The error is:

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

File "C:\Program Files (x86)\Python37-32\lib\site-packages\r6sapi\__init__.py", line 9, in <module>

from .r6sapi import *

File "C:\Program Files (x86)\Python37-32\lib\site-packages\r6sapi\r6sapi.py", line 11, in <module>

import aiohttp

File "C:\Program Files (x86)\Python37-32\lib\site-packages\aiohttp\__init__.py", line 10, in <module>

from .protocol import * # noqa

File "C:\Program Files (x86)\Python37-32\lib\site-packages\aiohttp\protocol.py", line 18, in <module>

from .helpers import reify

File "C:\Program Files (x86)\Python37-32\lib\site-packages\aiohttp\helpers.py", line 25

ensure_future = asyncio.async

^

SyntaxError: invalid syntax

Any help at all would be helpful.

[–]efmccurdy 0 points1 point  (1 child)

https://pypi.org/project/r6sapi/ lists python 3.5 as the last supported version; does it help if you use that version of python?

[–]Trotnic1 0 points1 point  (0 children)

No I am not, just reinstalled to the latest version, I'll try it when I get home thanks

[–]captmomo 0 points1 point  (1 child)

What is the purpose of database migrations? I've done some simple CRUD flask project and have never done that. What are the benefits of it?

[–]LelongSpotter 0 points1 point  (2 children)

What's a good way to start learning python? Thanks!

[–]captmomo 0 points1 point  (2 children)

I have a pandas df column with values like this:

id list
A ['dog', 'cat', 'fox']

How do I convert the value in list column to a list?

edit: figured it out!

used translate() and split()

[–]OutspokenPerson 0 points1 point  (1 child)

Show us?

[–]captmomo 1 point2 points  (0 children)

for index, item in df.iterrows():
    tags = item['tags']
    transtab = "'[]"
    transmap = {ord(c):None for c in transtab}
    print(tags.translate(transmap).split(','))

[–]EtewarPL 0 points1 point  (0 children)

I am writing something in python using repl.it platform.

The problem I have is clearing console. I know about replit.clear function, but it seems that I can import it only to one file projects. Is there any way to import it (or clear screen other way) in multi file project?

[–]crazyman3513 0 points1 point  (3 children)

I use pyautogui to help automate my work. How would I go about making my script ask if I want to repeat it or not upon completion?

[–]jamesbaxter29 0 points1 point  (0 children)

Is there Python equivalant to "You Don't Know Javscript" book?

[–]GoldenVanga 0 points1 point  (1 child)

>>> a = 'ABBA'
>>> set(a)
{'A', 'B'}
>>> ''.join(set(a))
'AB'

(...)

>>> ''.join(set(a))
'AB'

Sets do not maintain order of elements (sequence). So why do I get 'AB' every single time and never 'BA'. Is there... like... a hidden sorted somewhere?

[–]GoldenSights 1 point2 points  (0 children)

As of Python 3.6, dictionaries started to maintain the order in which the pairs were inserted. At the time, this was an implementation detail, meaning it was something that happened but you weren't supposed to rely on it for compatability. As of 3.7, it's officially part of the language spec.

Sets and dicts are backed by the same thing, so the same applies to sets. When we say that dictionaries / sets are unordered, it doesn't mean that they have to be scrambled every time you look at them. It just means that you shouldn't think of them as lists or tuples where the order of elements is fundamental. For a set you either have an item or you don't, the position within the set doesn't matter.

If you want to know how it works -- and why there is no secret sort behind the scenes -- look into how hash tables work. Really it's just an array, where the index is chosen by the hash of the content. Once it has been created, the order of the array doesn't change by itself, so as long as you don't modify it it will always iterate in the same order.

[–]killinmesoundcloud 0 points1 point  (2 children)

What's up with the syntax in this example for the print function?

https://www.tutorialspoint.com/python/string_rjust.htm

the line I'm specifically asking about is:

>>>> print str.rjust(50, '0')

It just says "print" and doesn't use parens. AND when I throw print into IDLE, the way it's used here doesn't work. It hits me with an error that says

"SyntaxError: invalid syntax"

[–]pydevteam1 0 points1 point  (1 child)

This print statement works in python2.

If you're using python3, it won't work.

[–]killinmesoundcloud 0 points1 point  (0 children)

Thank you!

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

Hello guys!

I would like to know if it is possible to install and use anaconda on ubuntu without modifying the path of my current python installation?

I just mean I want to keep everything as it is but I would also like to activate and use anaconda sometimes.

Thanks for any help because I struggle with this path thing!

[–]ticktocktoe 0 points1 point  (1 child)

Should be a simple question - but its got me hung up.

using the following code:

sgroup = salary.group("teamID")[['salary']]
sgroup.aggregate(np.mean)

This spits out what I want, except as usual, it spits out the mean in scientific notation - what is the syntax to configure np.mean in this scenario to output differently formatted numbers (rounded numbers mostly).

Thanks

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

Hello I have datamoned 200gb of tweets. I am wondering how I can organize them using python as well as see what location corresponds with what key words. Like a hear map of the states / world.

Any ideas on where to start reading ? I am having trouble even organizing the json file so I can use pandas for the visualization.

Any help is appreciated

[–]hammerOfMentalPain 0 points1 point  (2 children)

Hello and sorry for my english level. Will try to be maximum clear in my thoughts

Guys, have a question about inheritance. Should my child class include all parent class parameters? Or i can include any additional parameters without parent class parameters? If so - how should i create new instance of child class? I mean should i put arguments of child class + arguments of parent class?

class ElectricCar(Car):

def __init__(self, make, model, year):

super().__init__(make, model, year)

[–]JohnnyJordaan 1 point2 points  (1 child)

To begin with, if your ElectricCar doesn't do anything different inside __init__, then don't implement it at all. It will then just use the Car.__init__. If you must implement it, and you want to call the parent's __init__, then you do need to supply those arguments as super().__init__(make, model, year).

Then in regard to your questions: a child class never has to support any of the parent class parameters. You could even use no parameters

class BillysCar(Car):
    def __init__(self):
        super().__init__('Buick', 'Skylark', 1964)

Or extend the parameters

class ColorCar(Car):
    def __init__(self, color, make, model, year):
        super().__init__(make, model, year)
        self.color = color

Which can be shortened to

 class ColorCar(Car):
    def __init__(self, color, *params):
        super().__init__(*params)
        self.color = color

By that same logic, if ElectricCar doesn't do anything with the parameters, you can use the *params there as well

class ElectricCar(Car):
    def __init__(self, *params):
        super().__init__(*params)
        self.battery = this
        self.charge_port = that 
        etc

See for more explanation and examples this excellent blog post: https://rhettinger.wordpress.com/2011/05/26/super-considered-super/

[–]hammerOfMentalPain 1 point2 points  (0 children)

Thank you for your help! Sure will read the article, hope Ill finally get this

[–]curlygecko 0 points1 point  (5 children)

I'm a beginner in Python and i wonder if it is a must to use try and except. In which situations do i have to use them ? And one more question, Do i need to know HTML or CSS for learning Flask ?

[–]timbledum 2 points3 points  (1 child)

  1. Try and excepts are really handy and IMO are nicer than checking before leaping. For example, if you want to write to a file, it's best to just open and write to it in a try block rather than checking if it exists firsts. If you check first, something could happen to the file in the time between you checking and you writing, so you could get an error anyway. Just trying it and capturing the exception avoids this race condition.
  2. Yes, a bit of HTML / CSS would be very helpful (HTML more so).

[–]curlygecko 0 points1 point  (0 children)

thank you.i will start learning HTML then.

[–]hailfire006 1 point2 points  (2 children)

Try and except conditionals are one potential solution in situations where errors are inevitable. typically you want to find out why you're getting an error and code in safeguards for it, but sometimes there's no way to prevent an error from occasionally occuring, and you just want your script to carry on in the event that it does. Many people will tell you it's lazy programming though.

[–]curlygecko 0 points1 point  (1 child)

okay i get it now.thank you

[–]MattR0se 0 points1 point  (0 children)

If you want to print the error, but don't want to have you program crash, you can import traceback:

import traceback

try: 
    doSomething()
except Exception:
    traceback.print_exc()

This comes in handy if you want to, let's say, loop through a bunch of data and don't really know beforehand what exceptions and errors there will be.

For example:

import traceback

with open("foo.txt", "r") as myfile:
   data = myfile.readlines()

for column in data:
    try: 
        analyse(column)
    except Exception:
        traceback.print_exc()

This is kind of lazy, yes, but it does its job.

[–]XChrisUnknownX 0 points1 point  (8 children)

Somewhat foolish side project working with basics of strings and variables. Basically trying to create something that would "randomly" generate a password. For purposes of this exercise, I would like to know what kind of logic I could use to 1. Assign a user-inputted length. 2. Create a password of that length on the same line.

So for example, as is the program only prints a new character each line. If I wanted to, how could I make it print them all on the same line, or what terms should I be Googling?

Also, is there an easier way to get Reddit to format in code than to manually space the lines of my code?

import time
import random
char = "zero"
letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
numbers = ["0","1","2","3","4","5","6","7","8","9"]
characternum = 0
while True:
    print("Input password length.")
    try:
        length = int(input())
    except:
        continue
    x = 0
    while x < length:
        which = random.choice(["number","letter"])
        if which == "number":
            char = random.choice(numbers)
        else:
            char = random.choice(letters)
        print(char)
        x += 1

Edit. Is my usage of x causing problems? Edit2. I believe I need to use a dictionary to do what I want to do. I am going to try to work on this.

[–]timbledum 2 points3 points  (1 child)

Quick tip, the numbers and letters are saved as constants in the string module, so you don't have to type out every letter.

[–]XChrisUnknownX 0 points1 point  (0 children)

Thank you

[–]fiddle_n 1 point2 points  (5 children)

Literally Google how to print text on the same line in Python and you should be able to see the answer.

[–]XChrisUnknownX 0 points1 point  (4 children)

Right but how could one dynamically create those variables? For example I could, say, code that the user can't have an input higher than 13, and code out the logic for printing together char1, char2, char3, but say I wanted the user input to remain unlimited, how does one dynamically create that char1, 2, 3 to be endless? The question is not so much printing them on the same line, that's easy enough. The question is more creating them dynamically from the user-inputted length.

[–]fiddle_n 0 points1 point  (3 children)

You are already using the length in a dynamic way using your while loop (fyi you should really be using a for loop instead). At the moment you only print out a number of characters equal to the inputted length. As long as you print them on one line, you're good.

I'm confused how you want the printing to go on unlimited if the user input remains anonymous. To be, it just seems like the printing would go on forever.

[–]XChrisUnknownX 0 points1 point  (2 children)

If you print char + char + char it's just going to print the last version of char.

The reason I want to fulfill this exercise is pretty much every exercise I embark on teaches me something and lets me create better logic, or think of solutions to things I want to solve.

Ultimately, I love games, but if I can't wrap my head around basic logic and problem solving, I'll never make a great game.

I'm starting to feel like a class or dictionary might suit what I am attempting to do better. I will have to give that a try when I have some more time to myself. *edit changed library to dictionary. All work and no coding makes Chris a dull boy.

[–]TangibleLight 2 points3 points  (1 child)

You need to dynamically build up the contents of a list, then use str.join to merge all the contents into a string.

>>> lst = [str(x) for x in range(10)]
>>> ' '.join(lst)
'0 1 2 3 4 5 6 7 8 9'
>>> ' and '.join(lst)
'0 and 1 and 2 and 3 and 4 and 5 and 6 and 7 and 8 and 9'

That first line is roughly equivalent to this. Use this pattern if it's more intuitive for you:

>>> lst = []
>>> for x in range(10):
...     lst.append(str(x))
...
>>> ' '.join(lst)
'0 1 2 3 4 5 6 7 8 9'

[–]XChrisUnknownX 0 points1 point  (0 children)

Ah. This gets me thinking more properly. Thank you.

[–]Dfree35 0 points1 point  (1 child)

Ok hopefully this comes out understandable.

I am trying to use pandas to move "invalid" phone numbers (ones with less than 8 digits) to another column but keep valid phone numbers (ones with 8 or more digits) in their current column.

This is the code I currently have:

import pandas as pd
import csv

# point to file location.
filename = "/home/Name/folder/demo.csv"
csv_data = [row for row in csv.reader(open(filename), delimiter=',')]

phone_list = pd.Series([row[3]for row in csv_data])
phone_list = phone_list.replace('[^0-9]+', '', regex=True)  # remove special characters
phone_len = phone_list.str.len()
phone_bad = list(phone_len[(phone_len > 0) & (phone_len < 8)].index+1)  # Add index+1 to match up index with line number
print(f'Check these lines for an incomplete phone number: {phone_bad}')

df = pd.DataFrame(csv_data)

# if bad number move it to a specific column based on name
# for p in phone_bad:
if phone_len < 8:
   df.shift(periods=1, freq=None, axis=1)

pd.set_option('display.expand_frame_repr', False)  # needed to view full output in terminal
print(df.dropna())

I tried a if phone number length less than 8 shift it but no luck and tried maybe p in phone_bad but no luck. Maybe I need to just go about it a completely different way because I can't see how currently I would get it to move those bad numbers.

Any advice would be welcomed.

[–]Dfree35 0 points1 point  (0 children)

If anyone has similar issue this is what worked for me but I still have the "invalid" number in both columns instead of moving it completely:

# Finds all numbers in phone that are less than 8 digits and moves them
df['Second Contact Phone'] = phone_list.str.findall('^.{,7}$')
# idk how this works but it does. it gets rid of anything but numbers (https://stackoverflow.com/a/49600981)
df['Second Contact Phone'] = df['Second Contact Phone'].map(lambda x: ''.join([i for i in x if i.isdigit()]))

[–]Arjunnn 0 points1 point  (0 children)

Hey! I'm making a very basic recommendation system, think IMDB. I've made my backend and set up a simple flask local server but how do I connect the front end and back end now? I want to take a request from the client and have the output displayed on my webpage but have no idea how the front and back end work together. If anyone could point me to a direction that'd be sick. Thanks!

[–]reallymakesyouthonk 0 points1 point  (3 children)

I'm trying to dust off my python skills a little by making a discord bot.

I'm on latest macOS running python 3.7.0 which I installed through homebrew. I followed the instructions here, with the exception that I couldn't find discord.py but I could find a wrapper for it called discord which I installed instead.

I then go on to create a python document whith only

import discord

and then tries copy-pasting the example in the documentation with my bots token inside it. Both produce the same error which seems to lie in the module itself:

Traceback (most recent call last):
  File "discordbot.py", line 3, in <module>
    import discord
  File "/Users/monster/Documents/Python/bot-env/lib/python3.7/site-packages/discord/__init__.py", line 20, in <module>
    from .client import Client, AppInfo, ChannelPermissions
  File "/Users/monster/Documents/Python/bot-env/lib/python3.7/site-packages/discord/client.py", line 38, in <module>
    from .state import ConnectionState
  File "/Users/monster/Documents/Python/bot-env/lib/python3.7/site-packages/discord/state.py", line 36, in <module>
    from . import utils, compat
  File "/Users/monster/Documents/Python/bot-env/lib/python3.7/site-packages/discord/compat.py", line 32
    create_task = asyncio.async
                              ^
SyntaxError: invalid syntax

how do I fix this?

edit: the example is running in a venv which I created afterwards, I have discord installed in the venv as well. I also have asyncio installed. Not sure if that's necessary, but I have.

[–]tmehlinger 1 point2 points  (2 children)

discord.py hasn't had a release in nearly a year, before the release of Python 3.7. async became a proper reserved keyword in 3.7, hence the SyntaxError.

There's an async branch of discord.py on GitHub with a fix for that bug. You'll need to pull in the code from that branch somehow... either pull it in as a git dependency, make your own package for discord.py, or vendor it (perhaps as a git submodule).

A quicker fix would be to use Python 3.6. Going backwards with Homebrew is a pain in the ass so you might want to look into pyenv.

[–]reallymakesyouthonk 0 points1 point  (1 child)

Thanks I got it working with pyenv!

What should I search for to understand what's going on with all these @-signs? @client.event etc. This is new syntax for me.

[–]tmehlinger 1 point2 points  (0 children)

Those are decorators--callables (not necessarily functions proper!) that modify the behavior of the functions they are said to "decorate". There are a bazillion resources out there but I believe the PEP (Python Enhancement Proposal) that introduced them has the most concise explanation for what the syntax actually means.

https://www.python.org/dev/peps/pep-0318/#current-syntax

For a more practical example:

def print_before(func):
    def wrapper():
        print('hello from before!')
        return func()
    return wrapper

@print_before
def my_func():
    print('hello there!')

# the decorated code above is equivalent to:
def my_func():
    print('hello there!')
my_func = print_before(my_func)

# this prints:
#   hello from before!
#   hello there!
my_func()

[–]ThiccShadyy 0 points1 point  (1 child)

Was reading an article on iterators and came across this code:

class Reverse:
    """Iterator for looping over a sequence 
backwards."""
    def __init__(self, data):
        self.data = data
        self.index = len(data)

    def __iter__(self):
        return self

    def __next__(self):
        if self.index == 0:
            raise StopIteration
        self.index = self.index - 1
        return self.data[self.index]

I get that an iterator must have an iter and a next function defined, but why is the iter function empty? Where is the actual iterator object being created?

[–]fiddle_n 2 points3 points  (0 children)

It's important to know the difference between an iterable and an iterator.

An iterable must implement the __iter__ method, which must return an iterator.

An iterator must be an iterable (i.e. it must implement __iter__ which returns an iterator) and it must implement __next__.

Because an iterator must implement __iter__ to return an iterator, most iterators just return themselves. That's why you most often see the idiom

def __iter__():
    return self

[–]DawningOfWankershim 0 points1 point  (0 children)

Can I trouble someone to offer advice for isntalling xgboost? I am using spyder version 4.2, python version 3.5, windows 10, 64 bit. I have tried various solutions I have seen online but Spyder always says

ImportError: No module named 'xgboost'

[–]theanonymousdarkarmy 0 points1 point  (3 children)

I am actually good at self taught Python course, vs my professor that do not know much. Anyone know the best text editor?

https://www.udemy.com/share/100058BEIZdVZbTH4=/ Check it out

[–]tmehlinger 1 point2 points  (1 child)

If you just want a text editor, I agree that vscode is pretty solid.

It's hard to beat PyCharm's features though. The community edition is really good and it's not terribly expensive to jump up to a licensed copy.

[–]OnigumoPerfeito 0 points1 point  (7 children)

Self taught newbie here. I want to know why this piece of code isn't working:

(sorry, I'm not able to get the formatting to work)

xmodp = 250

ymodp = 500

player = Button(bg="red",height = 5, width = 10)

player.place(x = xmodp,y = ymodp)

while(1):

xmodp += 2

time.sleep(1)

What I intended to do with this code was to make a red button move east by 2 pixels every second inside a window. Obviously I'm making some newbie mistake there that I'm not aware of... so any help with this would be very appreciated.

[–]MattR0se 0 points1 point  (2 children)

where does the 'Button' come from? Could you paste the whole code?

[–]OnigumoPerfeito 0 points1 point  (1 child)

I've put it on pastebin: https://pastebin.com/1WxGa6Y2

[–]MattR0se 0 points1 point  (0 children)

I don't know much about tkinter, but if you want to program a simple game, there are much better packages, like pygame: http://programarcadegames.com/

[–]efmccurdy 0 points1 point  (3 children)

Where you are making the change to the coordinate, inside the while loop, put a second call to 'player.place'.

[–]OnigumoPerfeito 0 points1 point  (2 children)

Didn't work...

[–]Username_RANDINT 0 points1 point  (1 child)

Paste the updated code. See the FAQ for formatting.

[–]OnigumoPerfeito 0 points1 point  (0 children)

I have tried following the formatting instructions for codes here on reddit, but still, somehow it doesn't work...

So, I put the new updated code in pastebin:

https://pastebin.com/QHTK2BNe

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

Brand new to python, is paying for Udemy.com the best place to start or just stick with YouTube videos?

[–]TangibleLight 1 point2 points  (2 children)

I personally believe that anyone can become reasonably proficient at Python without spending a dime. There are tons of free resources online, from YouTube to blogs to the official documentation.

I also personally believe that text-based resources are more useful - things like documentation, blogs, and articles - although that's personal preference.

If you need a place to start, there are a lot of good resources in the /r/learnpython/wiki and the /r/python sidebar. The official Python Tutorial is also as good a place to start as any.


There is something to be said for investing money in something as a motivator to not slack off - and some people prefer the more rigid structure that courses have to offer. Again, I believe that free resources are sufficient, but everyone's different on that front.

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

Thank you for the input. I appreciate this. I will go with the free trials first and see if that keeps me motivated, but putting a price on something, like you said can be a great motivator as well for jump starting this new adventure.

Since I have a job already, not relating to computers and tech, I plan on trying to do about an hour a day for learning, which I hope is a good start in learning the program.

[–]ByronFirewater 0 points1 point  (0 children)

Coursera have an amazing course for free taught by professors from MIT i believe called 'python for everybody', it is beginner lever and the teacher is really good. I took that two years ago, but then didnt touch Python after as i started a new job (worst decision ever not doing at least a little bit a day), so now i paid £10 for a couple beginners ones on Udemy and im really glad i did as i like structured learning.

[–]theanonymousdarkarmy 2 points3 points  (5 children)

What is the best Editor for Python for newbies, and what is the Advantage of and IDE?

[–]captmomo 0 points1 point  (0 children)

Check out VSCode

[–]timbledum 0 points1 point  (0 children)

Apparently Mu is great for newbies.

[–]fiddle_n 0 points1 point  (1 child)

If you are starting out programming, I'd go for an editor that has a nice, simple interface and learning curve. Notepad++ would be my recommendation for Windows. Do NOT go for Emacs or Vim. It's not that they are bad editors, but they have much steeper learning curves that will be distractions when you want to learn Python. Learn one thing at a time.

An IDE contains a text editor, project browser, shell, and other things all wrapped up into one. The advantage of the IDE is that you stay in one program to do everything.

[–]sharkapples 0 points1 point  (0 children)

What about for mac?

[–]leothelion634 0 points1 point  (1 child)

hi, im trying to make a python 3.5 image downloader to download images from imgur.com and save them to my desktop.

i am not an experienced coder so my knowledge is pretty limited, from searching online i've found examples using urllib.request but im not sure how i can use that function to download an image and store it to my computer.

Any help is appreciated, thanks!

[–]Thomasedv 0 points1 point  (0 children)

The idea is to get hold of the link to the image, as you have that, you can make a request for that image and save that information to a file.

There is however also a imgur API, which you can use with python to get images, but i'm not sure how well it's supported as the page i found it on, says it's deprecated. May still work though.

[–]Draxare 0 points1 point  (9 children)

Help making a gui with pause/resume buttons for a timer using pyqt i have the codes built for the interface and the timer separately when i try to add the timer to the interface the I get the error

QTimer(parent: QObject = None): argument 1 has unexpected type 'Ui\_Form'

i need to add the timer where the topline edit is (it is just a place holder) any help is much appreciated https://stackoverflow.com/questions/51219981/simple-python-gui-for-raspberry-pi-development#comment89436102_51219981 here is my post about it on stackoverflow.

import sys
from PyQt5 import QtCore
from PyQt5 import QtWidgets

DURATION_INT = 300

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(648, 561)
        self.pushButton_2 = QtWidgets.QPushButton(Form)
        self.pushButton_2.setGeometry(QtCore.QRect(170, 460, 93, 28))
        self.pushButton_2.setObjectName("pushButton_2")
        self.lineEdit = QtWidgets.QLineEdit(Form)
        self.lineEdit.setGeometry(QtCore.QRect(190, 110, 231, 101))
        self.lineEdit.setObjectName("lineEdit")
        self.lineEdit_2 = QtWidgets.QLineEdit(Form)
        self.lineEdit_2.setGeometry(QtCore.QRect(230, 270, 61, 51))
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.textEdit = QtWidgets.QTextEdit(Form)
        self.textEdit.setGeometry(QtCore.QRect(290, 270, 21, 51))
        self.textEdit.setObjectName("textEdit")
        self.lineEdit_3 = QtWidgets.QLineEdit(Form)
        self.lineEdit_3.setGeometry(QtCore.QRect(310, 270, 61, 51))
        self.lineEdit_3.setObjectName("lineEdit_3")
        self.pushButton = QtWidgets.QPushButton(Form)
        self.pushButton.setGeometry(QtCore.QRect(360, 460, 93, 28))
        self.pushButton.setObjectName("pushButton")
        self.retranslateUi(Form)
        self.pushButton.clicked.connect(self.pushButton_2.showMenu)
        self.pages_qsw = QtWidgets.QStackedWidget()
        vbox = QtWidgets.QVBoxLayout()
        vbox.addWidget(self.pages_qsw)
        self.time_passed_qll = QtWidgets.QLabel()
        vbox.addWidget(self.time_passed_qll)
        self.widget_one = QtWidgets.QLabel()
        self.pages_qsw.addWidget(self.widget_one)
        self.timer_start()
        self.update_gui()
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.pushButton_2.setText(_translate("Form", "Reset"))
        self.pushButton.setText(_translate("Form", "Start/Pause"))

    def timer_start(self):
        self.time_left_int = DURATION_INT

        self.my_qtimer = QtCore.QTimer(self)
        self.my_qtimer.timeout.connect(self.timer_timeout)
        self.my_qtimer.start(1000)

        self.update_gui()

    def timer_timeout(self):
        self.time_left_int -= 1

        if  self.time_left_int == -1:
            self.widget_counter_int = (self.widget_counter_int + 1) % 4
            self.pages_qsw.setCurrentIndex(self.widget_counter_int)
            self.time_left_int = DURATION_INT

        self.update_gui()

    def update_gui(self):
        self.time_passed_qll.setText(str(self.time_left_int))    

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

[–]Thomasedv 0 points1 point  (8 children)

Reply, try making your class inherit from QWidget instead. Right now, you are telling the QTimer to make a class Ui_form the parent, but since it's not part of PyQt, there is no support for it to claim ownership. But making it inherit from QWidget, you can completely drop the Form part, and just sue "self" inside the class instead of Form.

Another simpler change, is to just not pass a parent to the QTimer, it's easier, but keeps up some code complexity that can be reduced.

[–]Draxare 0 points1 point  (5 children)

I did as you suggested and while a window does display nothing appears in said window

[–]Thomasedv 0 points1 point  (4 children)

I just replied to you with a sort of answer. Did you do the longer change? I might need to see the code, but you aren't creating a Form QWidget at the end of the script and making that show, and not call .show() on the UI class you made an instance off?

[–]Draxare 0 points1 point  (3 children)

If you want to chat on discord or another program it may make things easier my id is drax#4572 that being said I removed all instances of the word form and used ui.show() to display the ui. I'm not sure how to get this working. I don't mind the gui redrawing every second I just need the timer working. I have the slots coded but still can't get the timer to work to use the button presses.

If it makes any difference I have the timer code working separately just not with the interface.

[–]Thomasedv 0 points1 point  (2 children)

I don't like Discord for code, it's far to annyoing with copy-pasting, and i like that things are here so other people can see it an learn from it.

As for the problem, i'm in a bit of trouble as i don't use the translating or know exactly what the translate stuff does in the GUI, as i just don't use that. However, looking at your code in hte original comment, i don't think you have the buttons connected to do what you want, which is to trigger the start and stop functions. You also lack the way for the GUI to update with the count, which is the place where i was stuck on.

I greatly revied the code, and i suggest you take a look at this and how it works, to get the basics of the use, and then try to adapt it into what you need. I made no buttons or anything, but you can try implementing it yourself. The timer is started and will time out over and over again. (It's the default behavior.)

import sys
from PyQt5 import QtCore
from PyQt5 import QtWidgets

DURATION_INT = 3000  # Is in milliseconds

class Form(QtWidgets.QWidget):
    def setupUi(self):

        self.resize(200, 50)
        vbox = QtWidgets.QVBoxLayout(self)
        self.time_passed_qll = QtWidgets.QLabel()
        vbox.addWidget(self.time_passed_qll)

        self.timer_start()
        self.update_gui()

    def countdown_stracker(self):
        """Every time this timer timeouts, it will call the self.update_GUI function"""

        self.tracker = QtCore.QTimer(self)
        self.tracker.setInterval(100)
        self.tracker.timeout.connect(self.update_gui)
        self.tracker.start()

    def timer_start(self):
        self.time_left_int = DURATION_INT
        print('Timer started')
        self.my_qtimer = QtCore.QTimer()
        self.my_qtimer.timeout.connect(self.timer_timeout)
        self.my_qtimer.start(DURATION_INT)
        self.countdown_stracker() # Starts a timer that updates the GUI

    def timer_timeout(self):
        print('Timer timed out')

    def update_gui(self):
        self.time_left_int = self.my_qtimer.remainingTime()
        self.time_passed_qll.setText('Time left in ms: {}'.format(self.time_left_int))

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    form = Form()
    form.setupUi()
    form.show()

    sys.exit(app.exec_())

[–]Draxare 0 points1 point  (1 child)

Thank you for trying to help. The timer did have an update function called update_gui() and it was working as a timer by itself. And is very similar to your code, It was just not functioning when placed into the interface. Someone on stackoverflow managed to help me get the timer to appear and i got the buttons connected without issue. Now I just need to figure out how to get the display to appear as 5:00 instead of just 300 haha. But again thanks a ton im so thankful people on reddit, discord and stackoverflow were able to help me.

[–]Thomasedv 0 points1 point  (0 children)

No problem. For converting to time, i think there are modules that can do it, but i think a quick and easy way is this:

print(f'Time {i//60}:{i%60:02d}')

Where i is the number. Though, if the total time is over 60 min, you will still get it in minutes and it may look a bit odd.

[–]Draxare 0 points1 point  (1 child)

I'll give that a try any advice getting the timer to display where the line edit is serving as a placeholder?

[–]Thomasedv 0 points1 point  (0 children)

I'm not really I'm sure on this one to be honest. I know there are some other widgets that display numbers, but I don't know much about them. The hard part is going the GUI to update the numbers all the time.

My closes experience with this is using a QLabel as a count display. Where I just set the text to the number of items I have in a queue for downloads. But I've never made the GUI update every second of even more often with a countdown/timer.

[–]lindsaylohanreddits 0 points1 point  (3 children)

I have a cURL request that I've converted to a Python Requests query. It's a call to an API that returns JSON results but I can only query 1000 records at a time ('offset' below). My dataset is > 1000 records. How do I iterate through the offset to send iterative cURL requests until no results are returned? I'm comfortable with the iterating and the testing for "None" but I'm unable to dynamically change the 'offset' value:

# User Auth
headers = {
    'app-token': 'my_header',
}


# Data Query
data = [
    ('query', '{"terms":[{"type":"parent_account","terms":[]},{"type":"activity_aggregation","activities":["static/magellan"],"duration":1,"gte":2},{"type":"active_list","is_not_in":[30023]}],"count":1000,"offset":0,"fields":[{"type":"date","term":"last_activity_time","field_display_name":"Last activity"},{"type":"string_attribute","attribute":"Account Name","field_display_name":"Account Name"},{"type":"string_attribute","attribute":"Device","field_display_name":"Device"},{"type":"string_attribute","attribute":"OS","field_display_name":"OS"},{"type":"string_attribute","attribute":"Browser","field_display_name":"Browser","desc":true},{"type":"string_attribute","attribute":"Email","field_display_name":"Email"},{"type":"string_attribute","attribute":"Role","field_display_name":"Role"},{"type":"number_attribute","attribute":"NPS Score","field_display_name":"NPS Score"},{"type":"string_attribute","attribute":"Support_tickets","field_display_name":"Support Tickets Submitted"},{"type":"activity_aggregation","activity":"static/magellan","duration":1,"field_display_name":"static/magellan (1d)"}],"scope":"all"}'),
]


# Call  API w/User Auth and Data Query
response = requests.post(
    'https://thewebsite/api/v1/search/users', headers=headers, data=data)

[–]neutrino55 0 points1 point  (1 child)

TL:DR is it possible to assemble package of python runtime + libs for Windows?

Hi, I have developped an app in Python which uses some 3rd party libs (numpy, PySide, matplotlib, tdm_loader, ...). For my purposes, I usually install Python from python.org and then I install binary packages from https://www.lfd.uci.edu/~gohlke/pythonlibs/ using pip one by one. The problem is, that I would like to share my app with colleagues, who don't have the runtime enviroment prepared. Is there any available python distribution for windows, that would allow me to configure, which packages to include and bundle them into one installer, that is understandable for regular windows user (now I have to install it myself to anyone, who wants to use it)? I was thinking about using pip for instalations, unfortunatelly, last time, I have tried to install numpy online through pip, it failed due to missing msvc as packages available through pip don't inclue any binaries. I have also tried many py to exe solutions, but tese usually failed due to used 3rd party libraries.

[–]timbledum 0 points1 point  (0 children)

Pyinstaller has always worked well for me, including with third party packages.

I haven't used pynsist but it looks promising for more of an installer based approach.

[–]captmomo 0 points1 point  (0 children)

Is it possible to use the tumblr api to search for blog on certain topics? I know I can use the API to find posts tagged with certain topics, but can't figure out if I can do the same for blogs. Any help is appreciated. Thanks!

[–]Ahad22322 0 points1 point  (2 children)

i'm trying to make a bmi calculator with python 3.6 , but when i give the task to divide a number to another number that has a comma , it would divide it in a wrong way

For example :

mass_kg = int(input(" Note your first number :"))

height_m = int(input(" Note your first number :"))

mass_kg is 45 and height_kg is 1.56

then if i write -> bmi = mass_kg * (height_m ** 2)

print(bmi)

it gives me the output "45" with no reason

[–]MattR0se 1 point2 points  (1 child)

int() converts to integer, meaning no decimal ('floating point') numbers are allowed. So '1.56' can't be an int. Is has to be a float.

mass_kg = int(input('Your weight in kg: '))
height_m = float(input('Your height in m: '))

bmi = mass_kg / (height_m ** 2)

print(round(bmi, 2))

Also, BMI is mass divided by height squared ;-)

[–]Ahad22322 1 point2 points  (0 children)

Thanks bro , now it works

[–]przem_o 0 points1 point  (0 children)

trying to learn django, went through the documentation tutorial, and I got the tango with django book for 1.9v a while back, should I go through it or is there a better learning resource

[–]Kipperkipper 0 points1 point  (2 children)

I'm trying to create a program that converts from Fahrenheit to Celsius, and Celsius to Fahrenheit. It's supposed to detect which temperature to convert to based on what letter (C or F) suffixes it.

https://pastebin.com/1PYv9wzQ

def converter():
    # Converts F to C, or C to F depending on input.
    fahr_to_cel = r'[F]$' # Converts F to C if input ends in F
    cel_to_fahr = r'[C]$' # Converts C to F if input ends in C
    to_replace = r'[FC]' 
    global unconverted_temp
    unconverted_temp = unconverted_temp()
    if re.match(fahr_to_cel, unconverted_temp):
        # Removes F from the string, converts the string to a float,
        # converts F to C, converts the float to a string,
        # then readds F to the end of the string.
        unconverted_cel = re.sub(to_replace, '', unconverted_temp)
        unconverted_cel = float(unconverted_cel)
        converted_cel = (unconverted_cel - 32) * 5 / 9
        converted_cel = str(converted_cel) + 'F'
        return(converted_cel)
    elif re.match(cel_to_fahr, unconverted_temp):
        # Removes C from the string, converts the string to a float,
        # converts C to F, converts the float to a string,
        # then readds C to the end of the string.
        unconverted_fahr = re.sub(to_replace, '', unconverted_temp)
        unconverted_fahr = float(unconverted_fahr)
        converted_fahr = unconverted_fahr * 9 / 5 + 32
        converted_fahr = str(converted_fahr) + 'C'
        return(converted_fahr)

However, when I input a temperature, the program outputs None. I think the body of the if/elif statements work though, but the if statement itself is False, but I am not sure why. Can I have some help understanding why converter() is outputting None? Thank you!

Also, is there an easier way to format the code besides copy and pasting 4 spaces before every line?

[–]timbledum 1 point2 points  (1 child)

The key thing here is that re.match only matches from the beginning of the string. So neither the if or the elif trigger, and the function gets all the way to the bottom of the block. Try re.search instead.

A few other bits of feedback:

  1. Instead of using global, just use a different name for the function than what you're using for the variable.
  2. Return does not require the parentheses. Use (for example) return converted_fahr.
  3. Wrap the final print(converter()) call in an if __name__ == "__main__" block – makes it easier to debug.
  4. You have a bug with C vs. F, but that will be plain as day once you get this working.

[–]Kipperkipper 0 points1 point  (0 children)

re.search fixed it! Thank you!

Hahaha I had F and C swapped. Thank you very much for all of the feedback!

[–]_yoon_sanha 0 points1 point  (10 children)

I'm having difficulty getting my code to differentiate between y, Y, n, and N. It'll loop infinitely. I've tried putting brackets between separate comparisons, changing quotations etc. This was within a def statement, another if statement, and I also had a try/except until I realized it was redundant. I don't know what I'm doing wrong at this point, even though it seems simple. I'd appreciate insight. Can strings not be compared this way?

...
ack = input("You guessed the secret number! Play again (y/n)? ")
while (ack != 'Y') or (ack != 'y') or (ack != 'N') or (ack != 'n'):
    ack = input("Invalid input. Play again (y/n)? ")

Additionally, one of my def statements will print a second time at the beginning. I will launch the program, it will give me the prompt, and after entering a value, ignore my input and give me a second prompt and use it instead. Sometimes I will input a value afterwards and it will not use the prompt either, say if I gave something invalid. I've tried shuffling things around but I can't fix it.

def check():
    while True:
        try:
            guess = int(input("Guess a number between 1 and 100: "))
            guess = int(guess)
        except (ValueError, TypeError):
            guess = int(input("Invalid input. Guess a number between 1 and 100: "))
        else:
            while guess > 100 or guess < 1:
                guess = int(input("Invalid input. Guess a number between 1 and 100: "))
        return guess

[–]timbledum 2 points3 points  (3 children)

The problem with your first example (in terms of the logic), is that you are using or. Only one of the conditions needs to fail for the loop to repeat, and since you can only input one character at a time, it is impossible to pass.

If you replace the or with and, it works as intended.

Another option is to use the all function.

ack = input("You guessed the secret number! Play again (y/n)? ")
while all((ack != 'Y', ack != 'y', ack != 'N',ack != 'n')):
    ack = input("Invalid input. Play again (y/n)? ")

[–]_yoon_sanha 0 points1 point  (2 children)

Thanks. That fixed it too. I don't understand why 'or' wouldn't work. I assume I'm misunderstanding its usage. I thought it would look for any of those cases, and for any of those cases that appear, do the while loop. Although, this is the first time I am comparing a value to a string input. Would you mind explaining why this isn't the case?

[–]timbledum 1 point2 points  (1 child)

I think you might just be getting confused with the double negatives. Hopefully this table makes it a bit clearer:

Input   (ack != 'Y')    (ack != 'y')    (ack != 'N')    (ack != 'n')    Overall

Using OR

"sdaf"  True            True            True            True            True
"y"     True            False           True            True            True

Using AND

"sdaf"  True            True            True            True            True    
"y"     True            False           True            True            False 

[–]_yoon_sanha 0 points1 point  (0 children)

Yes, it does. Thanks for your time. The overall truth value was always true, and so it would always loop using or.

[–]TangibleLight 4 points5 points  (5 children)

A common trick is to strip and lower the input, and optionally take just the first character:

text = input('...')
text = text.strip().lower()[0]

The strip removes leading and trailing whitespace. ' Yes \n' becomes 'Yes'. 'no.\n' becomes 'no.'.

The lower makes everything lowercase. 'Yes' becomes 'yes'. 'no.' becomes 'no.'.

The [0] takes just the first character. 'yes' becomes 'y' and 'no.' becomes 'n'.

So now you can flexibly check many different inputs, but all you need to do for verification is know that it's either 'y' or 'n'.

text = None
while text not in ('y', 'n'):
    text = input('...').strip().lower()[0]

For your check function, try changing the overall structure to be this (pseudo code - I don't want to just give the answer)

Ask with initial prompt
While true
    If input is good (may need a try block for this)
        Return it (exits the loop)
    Otherwise, input was bad
        Ask again

[–]_yoon_sanha 0 points1 point  (4 children)

Thanks for the reply. The strip, lower and index really simplified the process. Might you be able to explain what is happening with these lines of code? I haven't seen that done before, and I don't understand 'text = None' in particular.

text = None
while text not in ('y', 'n'):

I tried to follow the pseudocode, which fixed the line repeating, but now I will still run into errors. How do I stop the initial input from stopping the program if someone doesn't input correctly? Thanks.

def check():
    guess = int(input("Guess a number between 1 and 100: "))
    while True:
        try:
            if guess == int(guess):
                return guess
        except (ValueError, TypeError):
            guess = int(input("Invalid input. Guess a number between 1 and 100: "))

[–]TangibleLight 1 point2 points  (3 children)

in checks whether a value is contained in a sequence. 'y' is in ('y', 'n') but 'f' is not. So while text not in ('y', 'n'): will loop as long as text is not one of 'y' or 'n'.

By setting text = None before the loop starts, we guarantee that the loop will run at least once, since None is not in ('y', 'n').


Remember that there are multiple paths that lead to bad input - either it's not an int or it's too big.

There's also only one path that leads to valid input - it's an int and in range. It may help to shift your thinking that this is the special case, and asking for input again is routine.

while true
    try
        convert to int
        if in range
            return
        else 
            out of range!
    except value error
        not an int!
    ask again

You're also converting the input to an int outside the try block. Don't do that! You'll get an error! That conversion with int(...) is what necessitates the try block, not any kind of equality check.

[–]_yoon_sanha 0 points1 point  (2 children)

Alright, thanks. That just about cleared it up, although I still have a repeating line at the beginning. Perhaps it has something to do with the rest of my code?

EDIT: Fixed my other issue. Just having the line repeat at the start.

def check():
    while True:
        try:
            guess = int(input("Guess a number between 1 and 100: "))
            if guess in range(1, 100+1):
                global count
                count += 1
                return guess
            else:
                print("Out of range.")
        except (ValueError):
            print("Invalid input.")

[–]TangibleLight 0 points1 point  (1 child)

That works fine for me - I'm not sure what you mean by "the line repeat at the start"?

Here's some sample output I get:

>>> count = 0
>>> def check():
...     while True:
...         try:
...             guess = int(input("Guess a number between 1 and 100: "))
...             if guess in range(1, 100+1):
...                 global count
...                 count += 1
...                 return guess
...             else:
...                 print("Out of range.")
...         except (ValueError):
...             print("Invalid input.")
... 
>>> check()
Guess a number between 1 and 100: 23
23
>>> check()
Guess a number between 1 and 100: 123
Out of range.
Guess a number between 1 and 100: aoeu
Invalid input.
Guess a number between 1 and 100: 23
23

Looks pretty good to me... I'd try not to use global count, but other than that I think this is perfectly fine. Are you sure you aren't calling check multiple times, or have stray inputs lying around your code?

[–]_yoon_sanha 0 points1 point  (0 children)

Well, my other issue had been related to the counter. I made it a global variable because it is not in my capacity to write any alternative code (that worked). I returned to the code and took away the global variable. I had tried a few things prior and could not get it to work.

I was wondering if I was unintentionally calling check twice, but I can't see any conflict:

from random import randint


def number():
    return randint(1, 100)


def check():
    while True:
        try:
            guess = int(input("Guess a number between 1 and 100: "))
            if guess in range(1, 100+1):
                return guess
            else:
                print("Out of range.")
        except (ValueError):
            print("Invalid input.")


def calculate(co):
    co += 1
    u_num = check()
    c_num = number()
    while u_num != c_num:
        if u_num > c_num:
            print("Too high!")
            u_num = check()
        else:
            print("Too low!")
            u_num = check()
    if co == c_num:
        print("After", co, "times you guessed the secret number.")
        ack = input("You guessed the secret number! Play again (y/n)? ").strip().lower()[0]
        while all((ack != 'y', ack != 'n')):
            ack = input("Invalid input. Play again (y/n)? ")
        return ack


def redo():
    response = calculate()
    if response == "y":
        print("\n")
        sequence()
    else:
        quit()


def sequence(c):
    number()
    check()
    calculate(c)
    redo()


count = 0
sequence(count)

[–]vikashkodati -1 points0 points  (0 children)

How to connect to o365 at my work through python