QUIZ: How well do you know Python?

Imma give myself an extra point for that, regardless if I got the question right or not :stuck_out_tongue:

18/20

I also failed at literals :slight_smile: (string ones by lack of enough attention, int ones by lack of knowledge…).

bruhh I thought 0xCOFFEE was 0xC0FFEE so i got it wrong…
can you pls state in parenthesis that it’s a O and not a 0?

I changed the font on that, so it ought to be more readable now.

image
Can you pls make it so that the O is wider?

I don’t get a lot of control. All I can do is select a font. It’s up to your browser and to Google Forms how it shows.

TBH I could have done better if I’d wanted to create my own quiz engine from scratch, but that is WAY too much effort for a quick quiz.

At least with the font in the screenshot you can see that the 0 at the start is different from the O so the keen-eyed will notice. Worst case people can give themselves an extra point

:rofl:

Is it like atleast possible to list all correct answers in the comments section of each question when graded?

You should get that as you answer each question, I think? If not, it would be after the final grade, there should be a button to show it.

That only happens if you get the question wrong

See: image hosted at ImgBB — ImgBB and image hosted at ImgBB — ImgBB

(I put the image in a link as to not give any spoilers for the answers)

Ah, that’s curious. Well, if anyone feels like making a better quiz engine, I’d be happy to switch, but for now there’s no easy fix.

since this is a quiz on google forms, you can press “add feedback” at the bottom of the question, and then under “correct answers” you can say “{a} {b} {c} are all correct” or something

also: why does this output what it does?

When you open a class block, you create a new nested scope, which will become the class attributes. So we have a global x, and then a new scope with a new x. The final print(x) sees this inner variable and thus prints 2. However, a function inside the class scope (which would normally be a method) does not implicitly see class attributes as variables - this is in contrast to a lot of other languages, which make that possible - and so it sees the global variable instead.

(The fact that the class itself is also called x is a red herring here as it won’t be assigned to until AFTER the block finishes.)

Having a function like this, inside a class but not accepting self a a parameter, is legal; most commonly, you’ll see this sort of thing decorated with @staticmethod to ensure that it behaves identically whether called on the class or an instance of that class.

Guido van Rossum will send you a letter of disappointment

from pathlib import Path

class FileReader:
    def __init__(self, path: Path) -> None:
        self._path = path

    def read(self) -> str:
        file = open(str(self._path), "r")
        content = file.read()
        file.close()
        return content

When am I receiving my letter? XD.

That’s hilarious! Where can I find more quizzes like this?

Well, the ones I made for this thread and its companion highlighted some rather nasty flaws in the quiz engine I was using, so I’m disinclined to make any more on Google Forms. But I’ll tell you what: If you find (or make!) a good quiz engine, I’ll come up with another set of questions. It’s been a while, and I can draw on some of the newer features - I like the quizzes to not just be “yes, good, you got that all correct” but “hey, here’s something new and cool”.

What we need from the quiz engine:

  • Free to use. I don’t want to pay money just to find that it’s not great. People have different levels of tolerance for ads, so the less intrusive, the better.
  • Web access. It’s most convenient for people to be able to click a link and take the quiz. Preferably, no login required.
  • Multiple choice questions where I enter one question and its (usually four) answers
  • Automatic randomization of the answer order; if that can be disabled for specific questions, great, but otherwise no big deal
  • Questions with multiple correct answers - selecting any correct answer counts as getting the question right
  • Show people which answer(s) was/were correct as soon as they’ve committed to a response
  • A decent font so we can distinguish 0 from O
  • Anything else you notice from the above posts.

It’s a lot to ask for, which is why I haven’t gone looking again (I tested out quite a number of quiz engines before making these quizzes!). It was a LOT of fun coming up with the questions, and people definitely enjoyed the answers; the only un-fun parts where the technological limitations and issues.

By the way: Your example code here has a slightly different, and smaller, issue than the shorter example from the quiz open(fn).read() - the risk is the same, but it’s less likely to happen. In your example, an exception could be raised after the file’s opened and before it’s closed, which would bail you out of the function and not close the function. With the shorter version, it’s relying on the file object being garbage collected and the file closed by the destructor, which is much more likely to cause issues (and it is ALSO susceptible to exceptions, just like your example). So your version is strictly better than the one from the quiz, but still vulnerable to leaving the file open unnecessarily.

Why’s this a problem? Well, there are a couple of reasons. One is that, if you open a file, discard it, and then try to open it again, it might still be open. Consider:

def more_spam(n):
    current_spam = int(open("spamcount").read() or "0")
    print(current_spam + n, file=open("spamcount", "w"))

In CPython, this will probably work, but it isn’t guaranteed. In other Python implementations, it might work but might consistently fail. Using two separate context managers guarantees that the second one won’t be entered until the first one has completed.

The other risk is that the file objects could pile up, running you out of open file slots (file descriptors, or whatever your platform uses). There’s usually some sort of limit. So, what happens when you try to quickly read a huge number of files?

def total_line_count(dir):
    lines = 0
    for file in os.listdir(dir):
        lines += sum(1 for line in open(file))
    return lines

Without ensuring that the previous file is closed before the next one is opened, this could theoretically churn through thousands of file descriptors very quickly. And it’d be an absolute pain to try to diagnose, since triggering a garbage collection run would reset your open file count.

And yes, I know how much of a pain this sort of thing is to deal with, because I’ve dealt with it :slight_smile: You can’t ALWAYS use a context manager, but whenever you can, it does save you a lot of hassle.

I will never be able to remember the difference between “parameters” and “arguments”.

Why can lambdas have local variables? Is that because technically function parameters are treated as local variables?

Formal parameters define what a function can accept. Actual arguments are the ones you yell at the function to make it work… oh wait, that’s abuse. Close enough though.

They are, and that’s TECHNICALLY enough to have locals, but if that were all, I wouldn’t have made the question. However, they can also have other locals thanks to the walrus operator:

>>> a = 1
>>> f = lambda: (a := 2)
>>> f()
2
>>> a
1

The lambda function has a local variable called a that doesn’t conflict with the outer variable with the same name. This definitely isn’t something you should be doing often [1], but it’s legal, and could be useful in a larger construct.

Also, a list comprehension inside a lambda function will have its own locals, although that depends on your Python version.


  1. nor is assigning a lambda function directly to a simple name, but that’s just to make a compact example ↩︎

15/20 I’m happy with that :slight_smile: