skip to navigation
skip to content

Planet Python

Last update: November 29, 2020 01:48 PM UTC

November 29, 2020


Philippe Normand

Catching up on WebKit GStreamer WebAudio backends maintenance

Over the past few months the WebKit development team has been working on modernizing support for the WebAudio specification. This post highlights some of the changes that were recently merged, focusing on the GStreamer ports.

My fellow WebKit colleague, Chris Dumez, has been very active lately, updating the WebAudio implementation …

November 29, 2020 12:45 PM UTC

November 28, 2020


Karim Elghamrawy

What Programming Language Should I Learn First?

The post What Programming Language Should I Learn First? appeared first on Afternerd.

November 28, 2020 08:42 PM UTC


Doug Hellmann

imapautofiler 1.9.0

imapautofiler applies user-defined rules to automatically organize messages on an IMAP server. New Features Start using reno for managing release notes. Details Add unit tests for config (contributions by Christopher Arndt) Add ‘check_hostname’ server option (contributions by Christopher Arndt) use the correct default ssl context document debian dependencies update documentation for templating destination folders add …

November 28, 2020 04:31 PM UTC


Weekly Python StackOverflow Report

(cclii) stackoverflow python report

These are the ten most rated questions at Stack Overflow last week.
Between brackets: [question score / answers count]
Build date: 2020-11-28 15:49:05 GMT


  1. Weird scoping behavior in python - [21/1]
  2. insertion sort worst time complexity for near sorted array? - [7/2]
  3. Keras vertical ensemble model with condition in between - [7/1]
  4. In Python, is it possible to restrict the type of a function parameter to two possible types? - [5/4]
  5. How to quickly check if domain exists? - [5/4]
  6. Why is my key movement not working properly? - [5/2]
  7. Import of files in one folder from another folder - [5/2]
  8. Why does Python detect the symbol "²" as a digit? - [5/2]
  9. Why is random.shuffle so much slower than using sorted function? - [5/1]
  10. Behavior when two superclasses has the same method - [5/0]

November 28, 2020 03:49 PM UTC


EuroPython

EuroPython videos all on archive.org

Over the last few weeks, Anthon van der Neut, our media work group chair for EP2015 and EP2016, put in a lot of effort into getting all our conference videos on archive.org, the Internet Archive.  Archive.org is not meant as an alternative for YouTube to watch the videos, but it allows you to retrieve the original uploads, and as such also functions as a backup location for the us and the community.

He first downloaded all videos from our YouTube account (over 2.5TB as of this writing), then enriched the meta data based on the talk information we have on the websites, fixed issues he found, and then uploaded the videos and meta data to our archive.org account. Overall, around 40 hours of work went into this.

We now have more than 1000 conference videos available on our archive.org account, covering EP2014 - EP2020.

image

EuroPython videos on archive.org

Thanks, Anthon, for making this possible !

Enjoy,

EuroPython 2021 Team
https://www.europython-society.org/

November 28, 2020 12:00 PM UTC

November 27, 2020


Trey Hunner

Python Cyber Monday Sales 2020

This post is a compilation of different Cyber Monday deals I’ve found related to Python and Python learning.

Python Morsels weekly screencasts

Let’s get the self-promotion out of the way first.

I announced a couple days ago that you can now get one year of Python screencasts as well as mini-blog posts for $50/year (with at least one new screencast each week). This also includes one Python exercise each month. I haven’t set a concrete end date to this “sale” (it’s actually more of a newly announced service that will be increasing in price in early 2021).

You can find my article on the Python Morsels screencasts sale here.

Talk Python course bundle

You can get every Talk Python course that’s been made so far for just $250. There’s 28 courses currently and the bundle also includes courses published through October 2021.

PyBites sales

PyBites is offering PyBites Premium+ Access for 2 months for $24 and Introductory Bites Course for $15 (both effectively 70% off) during their Black Friday and Cyber Monday sale.

Reuven Lerner’s Python courses and exercises

Reuven Lerner is offering 40% off all his products (Python courses, Weekly Python Exercises, and product bundles) through Monday.

Matt Harrison’s Modern Python workshop

Matt Harrison’s Modern Python workshop is $500 (50%) off through Monday with coupon code EARLYBIRD and and his other courses (including Python data science and pandas courses) are 40% off through Monday with code BLACKFRIDAY.

Speed Up Your Django book

Adam Johnson’s Speed Up Your Django book is 50% off through Monday. Python Morsels is a Django-powered site and I could use this book, so I’ll be buying a copy for myself as well.

Mike Driscoll’s Python books

Mike Driscoll is offering a sale on all his Python books (each is $15 or less during the sale).

Brian Okken’s Pytest book (Pragmatic Bookshelf)

Pragmatic Bookshelf is offering 40% off all books with the code turkeysale2020, including Brian Okken’s Pytest book which is just under $15 with the coupon.

No Starch Press Python books

No Starch Press is also running a 33% off sale on their Python books (with books by Al Sweigart, Eric Matthes, and many others), though the sale ends before Monday.

Real Python subscription

Real Python is offering an annual subscription for $200/year and 20% of that goes to the Python Software Foundation.

Pluralsight subscription

We’re now moving into “I’m really not actually sure what you’re getting” sales. Pluralsight is running a Black Friday sale this year: $180/year for a subscription. I’m not sure whether this is one year for $180 but the subscription renews at the regular price of $300/year or whether it’s $180/year indefinitely (the fact that they don’t specify is a bit concerning).

100 Days of Code Python and other Udemy courses

There’s a 100 Days of Code Python course course on sale for just $13 on Udemy through mid next week. I haven’t heard anything about it but it looks like it includes a lot.

There are also various other Udemy Python courses on sale, like Automate The Boring Stuff, though many of these sales end within the next 24 hours (through Black Friday only).

Lots of courses, books, screencasts, exercises, live workshops on sale

Don’t go too wild on sales.

I know that I wouldn’t want anyone subscribing to Python Morsels unless they think they’ll actually commit at least an hour over the next year to watch screencasts. I imagine many other Python educators feel similar about purchases that go to waste.

Look through the sales above and think about what you could use. What works well with the way you learn and what would you actually make a habit to use after you’ve purchased it?

If you have a question about the Python Morsels screencasts/exercises, email me. If you have questions about other sales, email the folks running those sales (make sure to do it now in case they take a day or two to get back to you).

Also if you’ve found other Python sales I’ve missed above, please comment or email me to let me know about them.

November 27, 2020 09:20 PM UTC


Stack Abuse

Seaborn Distribution/Histogram Plot - Tutorial and Examples

Introduction

Seaborn is one of the most widely used data visualization libraries in Python, as an extension to Matplotlib. It offers a simple, intuitive, yet highly customizable API for data visualization.

In this tutorial, we'll take a look at how to plot a histogram plot in Seaborn. We'll cover how to plot a histogram with Seaborn, how to change Histogram bin sizes, as well as plot Kernel Density Estimation plots on top of Histograms and show distribution data instead of count data.

Import Data

We'll be using the Netflix Shows dataset and visualizing the distributions from there.

Let's import Pandas and load in the dataset:

import pandas as pd

df = pd.read_csv('netflix_titles.csv')

How to Plot a Histogram with Seaborn?

Well, Seaborn doesn't have a regular histplot() function anymore. Specifically, Seaborn has different types of distribution plots that you might want to use.

These plot types are: Distribution Plots (displot()) and Count Plots (countplot()). By default, the displot() is the closest you'd get to Matplotlib's hist() function, as the default approach of a displot() is to plot a histogram.

Note: Since Seaborn 0.11, distplot() became displot(). If you're using an older version, you'll have to use the older function as well.

Let's start plotting.

Plot Histogram/Distribution Plot (displot) with Seaborn

Let's go ahead and import the required modules and generate a Histogram/Distribution Plot.

We'll visualize the distribution of the release_year feature, to see when Netflix was the most active with new additions:

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import seaborn as sns

# Load the data
df = pd.read_csv('netflix_titles.csv')
# Extract feature we're interested in
data = df['release_year']

# Generate histogram/distribution plot
sns.displot(data)

plt.show()

Now, if we run the code, we'll be greeted with a histogram plot, showing the count of the occurences of these release_year values:

histogram plot seaborn

Plot Histogram with Density Information with Seaborn

Now, as with Matplotlib, the default histogram approach is to count the number of occurences. Instead, you can visualize the distribution of each of these release_years in percentages.

Let's modify the displot() call to change that:

# Extract feature we're interested in
data = df['release_year']

# Generate histogram/distribution plot
sns.displot(data, stat = 'density')

plt.show()

The only thing we need to change is to provide the stat argument, and let it know that we'd like to see the density, instead of the 'count'.

Now, instead of the count we've seen before, we'll be presented with the density of entries:

histogram density information seaborn

Change Histogram Plot Bin Size with Seaborn

Sometimes, the automatic bin sizes don't work very well for us. They're too big or too small. By default, the size is chosen based on the observed variance in the data, but this sometimes can't be different than what we'd like to bring to light.

In our plot, they're a bit too small and awkwardly placed with gaps between them. We can change the bin size either by setting the binwidth for each bin, or by setting the number of bins:

data = df['release_year']

sns.displot(data, binwidth = 3)

plt.show()

This will make each bin encompass data in ranges of 3 years:

change histogram bin sizes seaborn

Or, we can set a fixed number of bins:

data = df['release_year']

sns.displot(data, bins = 30)

plt.show()

Now, the data will be packed into 30 bins and depending on the range of your dataset, this will either be a lot of bins, or a really small amount:

histogram bin number seaborn

Another great way to get rid of the awkward gaps is to set the discrete argument to True:

data = df['release_year']

sns.displot(data, discrete=True)

plt.show()

This results in:

histogram discrete data seaborn

Plot Histogram with KDE

A common plot to plot alongside a Histogram is the Kernel Density Estimation plot. They're smooth and you don't lose any value by snatching ranges of values into bins. You can set a larger bin value, overlay a KDE plot over the Histogram and have all the relevant information on screen.

Thankfully, since this was a really common thing to do, Seaborn lets us plot a KDE plot simply by setting the kde argument to True:

data = df['release_year']

sns.displot(data, discrete = True, kde = True)

plt.show()

This now results in:

plot histogram with kde seaborn

Plot Joint Plot Histogram with Seaborn

Sometimes, you might want to visualize multiple features against each other, and their distributions. For example, we might want to visualize the distribution of the show ratings, as well as year of their addition. If we were looking to see if Netflix started adding more kid-friendly content over the years, this would be a great pairing for a Joint Plot.

Let's make a jointplot():

df = pd.read_csv('netflix_titles.csv')
df.dropna(inplace=True)

sns.jointplot(x = "rating", y = "release_year", data = df)

plt.show()

We've dropped null values here since Seaborn will have trouble converting them to usable values.

Here, we've made a Histogram plot for the rating feature, as well as a Histogram plot for the release_year feature:

joint histogram plot seaborn

We can see that most of the added entries are TV-MA, however, there's also a lot of TV-14 entries so there's a nice selection of shows for the entire family.

Conclusion

In this tutorial, we've gone over several ways to plot a histogram plot using Seaborn and Python.

If you're interested in Data Visualization and don't know where to start, make sure to check out our book on Data Visualization in Python.

Data Visualization in Python, a book for beginner to intermediate Python developers, will guide you through simple data manipulation with Pandas, cover core plotting libraries like Matplotlib and Seaborn, and show you how to take advantage of declarative and experimental libraries like Altair.

Data Visualization in Python

Understand your data better with visualizations! With over 275+ pages, you'll learn the ins and outs of visualizing data in Python with popular libraries like Matplotlib, Seaborn, Bokeh, and more.

November 27, 2020 08:28 PM UTC


Ned Batchelder

Mad Libs

When people ask what they should implement to practice programming, I often say, Mad Libs. It’s a game, so it might appeal to youthful minds, but it’s purely text-based, so it won’t be overwhelming to implement. It can start simple, for beginners, but get complicated if you are more advanced.

Mad Libs is a language game. One person, the reader, has a story with blanks in it. The other player(s) provide words to go in the blanks, but they don’t know the story. The result is usually funny.

For example, the story might be:

There was a tiny     (adjective)        (noun)     who was feeling very     (adjective)    . After     (verb)    ’ing, she felt     (adjective)    .

(An actual story would be longer, usually a full paragraph.) The reader will ask for the words, either in order, or randomized:

Give me an adjective.
“Purple”.
Give ma a noun.
“Barn”.
A verb.
“Jump”.
Another adjective.
“Lumpy”.
Another adjective.
“Perturbed”.

Then the reader presents the finished story:

There was a tiny perturbed barn who was feeling very purple. After jumping, she felt lumpy.

To do this in software, the program will be the reader, prompting the user for words, and then output the finished story. There are a few different ways you could structure it, of different complexities:

Each of these has design choices to be made. How will you separate the text from the blanks? How will you indicate what kind of word goes in each blank? How complex a story structure will you allow?

There are other bells and whistles you can add along the way, for any of the stages of complexity:

If you are interested, you can read the details of how I approached it years ago with my son: Programming madlibs.

November 27, 2020 02:44 PM UTC


Stack Abuse

Convert Bytes to String in Python

Introduction

In this article, we'll take a look at how to convert Bytes to a String in Python. By the end of this article you will have a clear idea of what these types are and how to effectively handle data using them.

Depending on the version of Python you're using, this task will differ. Although Python 2 has reached its end of life, many projects still use it, so we'll include both the Python 2 and Python 3 approaches.

Convert Bytes to String in Python 3

Since Python 3, the old ASCII way of doing things had to go, and Python became completely Unicode.

This means that we lost the explicit unicode type: u"string" - every string is a u"string"!

To differentiate these strings from good old bytestrings, we're introduced to a new specifier for them - the b"string".

This was added in Python 2.6, but it served no real purpose other than to prepare for Python 3 as all strings were bytestrings in 2.6.

Bytestrings in Python 3 are officially called bytes, an immutable sequence of integers in the range 0 <= x < 256. Another bytes-like object added in 2.6 is the bytearray - similar to bytes, but mutable.

Convert Bytes to String with decode()

Let's take a look at how we can convert bytes to a String, using the built-in decode() method for the bytes class:

>>> b = b"Lets grab a \xf0\x9f\x8d\x95!"
# Let's check the type
>>> type(b)
<class 'bytes'>

# Now, let's decode/convert them into a string
>>> s = b.decode('UTF-8')
>>> s
"Let's grab a 🍕!"

Passing the encoding format, we've decoded the bytes object into a string and printed it.

Convert Bytes to String with codecs

Alternatively, we can use the built-in codecs module for this purpose as well:

>>> import codecs
>>> b = b'Lets grab a \xf0\x9f\x8d\x95!'

>>> codecs.decode(b, 'UTF-8')
"Let's grab a 🍕!"

You don't really need to pass in the encoding parameter, though, it is advised to pass it in:

>>> codecs.decode(b)
"Let's grab a 🍕!"

Convert Bytes to String with str()

Finally, you can use the str() function, which accepts various values and converts them into strings:

>>> b = b'Lets grab a \xf0\x9f\x8d\x95!'
>>> str(b, 'UTF-8')
"Let's grab a 🍕!"

Make sure to provide the encoding argument to str() though, otherwise you might get some unexpected results:

>>> str(b)
b'Lets grab a \xf0\x9f\x8d\x95!'

This brings us to encodings once again. If you specify the wrong encoding, the best case is your program crashing because it can't decode the data. For example, if we tried using the str() function with UTF-16, we'd be greeted with:

>>> str(b, 'UTF-16')
'敌❴\u2073牧扡愠\uf020趟↕'

This is even more important given that Python 3 likes to assume Unicode - so if you are working with files or data sources that use an obscure encoding, make sure to pay extra attention.

Convert Bytes to String in Python 2

In Python 2, a bundle of bytes and a string are practically the same thing - strings are objects consisting of 1-byte long characters, meaning that each character can store 256 values. That's why they are sometimes called bytestrings.

This is great when working with byte data - we just load it into a variable and we are ready to print:

>>> s = "Hello world!"

>>> s
'Hello world!'

>>> len(s)
12

Using Unicode characters in bytestrings does change this behavior a bit though:

>>> s = "Let's grab a 🍕!"

>>> s
'Lets grab a \xf0\x9f\x8d\x95!'
# Where has the pizza gone to?

>>> len(s)
17
# Shouldn't that be 15?

Convert Bytes to Unicode (Python 2)

Here, we'll have to use Python 2's Unicode type, which is assumed and automatically used in Python 3. This stores strings as a series of code points, rather than bytes.

The \xf0\x9f\x8d\x95 represents bytes as two-digit hex numbers as Python doesn't know how to represent them as ASCII characters:

>>> u = u"Let's grab a 🍕!"
u"Let's grab a \U0001f355!""

>>> u
"Let's grab a 🍕!"
# Yum.

>>> len(u)
15

As you can see above, the Unicode string contains \U0001f355 - a Unicode escaped character which our terminal now knows how to print out as a slice of pizza! Setting this was as easy as using the u specifier before the value of the bytestring.

So, how do I switch between the two?

You can get the Unicode string by decoding your bytestring. This can be done by constructing a Unicode object, providing the bytestring and a string containing the encoding name as arguments or by calling .decode(encoding) on a bytestring.

Convert Bytes to String Using decode() (Python 2)

You can also use the codecs.encode(s, encoding) from the codecs module.

>>> s = "Let's grab a \xf0\x9f\x8d\x95!"
>>> u = unicode(s, 'UTF-8')

>>> u
"Let's grab a 🍕!"

>>> s.decode('UTF-8')
"Let's grab a 🍕!"

Convert Bytes to String Using codecs (Python 2)

Or, using the codecs module:

import codecs

>>> codecs.decode(s, 'UTF-8')
"Let's grab a 🍕!"

Be Mindful of your Encoding

A word of caution here - bytes can be interpreted differently in different encodings. With around 80 different encodings available out of the box, it might not be easy to know if you've got the right one!

s = '\xf8\xe7'

# This one will let us know we used the wrong encoding

>>> s.decode('UTF-8')
UnicodeDecodeError: 'utf8' codec can't decode byte 0xf8 in position 0:
invalid start byte

# These two overlaps and this is a valid string in both

>>> s.decode('latin1')
øç

s.decode('iso8859_5')
јч

The original message was either øç or јч, and both appear to be valid conversions.

Conclusion

As programmers, there are some things we must constantly think about and actively prepare for in order to avoid pitfalls. This holds especially true on the lower levels, where we seldom go when we use a high-level language like Python as our daily driver.

Things like charsets, encodings and binary are there to remind us that our job is to code - to encode our thoughts into working solutions. Thankfully, a lot of this thinking becomes part of our routine after a few rounds at the keyboard.

In this article, we've gone over how to convert bytes to Strings in Python.

November 27, 2020 01:30 PM UTC


Reuven Lerner

This Black Friday, get 40% off all 25 of my Python, Git, and data science courses

It’s time: My Black Friday sale, with 40% off all 25 products in my online store, is live!

What am I offering?

How do you take advantage of this? Just use coupon code BF2020 at checkout. Or click on this link, which will apply it automatically at checkout.

Questions? Just e-mail me at reuven@lerner.co.il, or get me on Twitter as @reuvenmlerner.

The post This Black Friday, get 40% off all 25 of my Python, Git, and data science courses appeared first on Reuven Lerner.

November 27, 2020 01:13 PM UTC


Real Python

The Real Python Podcast – Episode #37: Teaching Python and Finding Resources for Students

One of the best ways to learn something well is to teach it. This week on the show, we have Kelly Schuster-Paredes and Sean Tibor from the Teaching Python podcast. Sean and Kelly teach middle school students Python and share their art and science of teaching Python on their podcast. They wanted to come on the show to talk about the Real Python articles, quizzes, and other resources they use when teaching their students.


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

November 27, 2020 12:00 PM UTC


Python Bytes

#209 JITing Python with .NET, no irons in sight

<p>Sponsored by us! Support our work through:</p> <ul> <li>Our <a href="https://training.talkpython.fm/"><strong>courses at Talk Python Training</strong></a></li> <li><a href="https://testandcode.com/"><strong>Test &amp; Code</strong></a> Podcast</li> <li><a href="https://www.patreon.com/pythonbytes"><strong>Patreon Supporters</strong></a></li> </ul> <p><strong>Michael #1:</strong> <a href="https://tonybaloney.github.io/posts/running-python-on-dotnet-5-with-pyjion.html"><strong>Running Python on .NET 5</strong></a></p> <ul> <li>by Anthony Shaw</li> <li>Talked about <a href="https://talkpython.fm/episodes/show/49/microsofts-jit-based-python-project-pyjion">pyjion way back when on episode 49 with Brett Cannon</a>.</li> <li>.NET 5 was released on November 10, 2020. It is the cross-platform and open-source replacement of the <a href="https://github.com/dotnet/core"><strong>.NET Core</strong></a> project and the <strong>.NET</strong> project that ran exclusively on Windows since the late 90’s. See <a href="https://www.youtube.com/playlist?list=PLdo4fOcmZ0oVWop1HEOml2OdqbDs6IlcI">the conference about it</a> if you want to go deeper.</li> <li>Performance: I just saw a SO post about someone <a href="https://stackoverflow.com/questions/29903320/why-is-my-computation-so-much-faster-in-c-sharp-than-python">complaining their Python was 31x slower than C#</a>.</li> <li>The most common way around this performance barrier is to compile Python extensions from C or using something like Cython.</li> <li>.NET 5 CLR comes bundled with a performant JIT compiler (codenamed RyuJIT) that will compile .NETs IL into native machine instructions on Intel x86, x86-64, and ARM CPU architectures.</li> <li>Pyjion is a project to replace the core execution loop of CPython by transpiling CPython bytecode to ECMA CIL and then using the .NET 5 CLR to compile that into machine code.</li> <li>It then executes the machine-code compiled JIT frames at runtime instead of using the native execution loop of CPython.</li> <li>A few releases of Python ago (CPython specifically, the most commonly used version of Python) in 3.7 a new API was added to be able to swap out “frame execution” with a replacement implementation. This is otherwise known as <a href="https://www.python.org/dev/peps/pep-0523/">PEP 523</a>.</li> <li>This extension uses the same standard library as Python 3.9.</li> <li>Will this be compatible with my existing Python code? What about C Extensions? <ul> <li>The short answer is- if your existing Python code runs on CPython 3.9 – <strong>yes</strong> it will be compatible.</li> <li>Tested against the full CPython “test suite” on all platforms. In fact, it was the first JIT ever to pass the test suite.</li> </ul></li> <li>Is this faster? The short answer a little, but not by much (yet).</li> <li>see also: https://twitter.com/anthonypjshaw/status/1328457723608928256?s=20 </li> </ul> <p><strong>Brian #2:</strong> <a href="https://www.python.org/dev/peps/pep-0621/"><strong>PEP 621 -- Storing project metadata in pyproject.toml</strong></a></p> <ul> <li>Progress on standardizing what goes into pyproject.toml</li> <li>Authors Brett Cannon, Paul Ganssle, Pradyun Gedam, Sébastien Eustace (of poetry), Thomas Kluyver (of flit), Tzu-Ping Chung</li> <li>Motivators of this PEP are: <ul> <li>Encourage users to specify core metadata statically for speed, ease of specification, unambiguity, and deterministic consumption by build back-ends</li> <li>Provide a tool-agnostic way of specifying metadata for ease of learning and transitioning between build back-ends</li> <li>Allow for more code sharing between build back-ends for the "boring parts" of a project's metadata</li> </ul></li> <li>Doesn’t change any existing core metadata</li> <li>Doesn’t attempt to standardize all possible metadata</li> <li>Included in table named <code>[project]</code>: <ul> <li>name</li> <li>version</li> <li>description</li> <li>readme</li> <li>requires-python</li> <li>license</li> <li>authors/maintainers</li> <li>keywords</li> <li>classifiers</li> <li>urls</li> <li>entry points</li> <li>dependencies/optional-dependencies</li> <li>dynamic </li> </ul></li> <li>There’s an example in the PEP that helps clear things up</li> <li>Many items have synonyms specified for flit/poetry/setuptools (presumably for backward compatibility)</li> </ul> <p><strong>Michael #3:</strong> <a href="https://www.engadget.com/github-youtube-dl-aftermath-222301386.html"><strong>GitHub revamps copyright takedown policy after restoring YouTube-dl</strong></a></p> <ul> <li>In October following a DMCA complaint from the Recording Industry Association of America (RIAA) it was taken down at GitHub. </li> <li>Citing a <a href="https://github.com/github/dmca/blob/master/2020/11/2020-11-16-RIAA-reversal-effletter.pdf">letter</a> from the Electronic Frontier Foundation (the EFF), GitHub says it ultimately found that the RIAA’s complaint didn’t have any merit. </li> <li>The RIAA argued the tool ran afoul of section 1201 of the US copyright law by giving people the means to circumvent YouTube’s DRM. </li> <li>the EFF dissects the RIAA’s claims, highlighting where the organization had either misinterpreted the law or how the code of YouTube-dl works. “Importantly, YouTube-dl does not decrypt video streams that are encrypted with commercial DRM technologies, such as Widevine, that are used by subscription videos sites, such as Netflix,” the organization points out when it comes to the RIAA’s primary claim.</li> <li>GitHub is implementing new policies to avoid a repeat of a repeat situation moving forward. First, it says a team of both technical and legal experts will manually evaluate every single section 1201 claim.</li> <li>If the company’s technical and legal teams ultimately find any issues with a project, GitHub will give its owners the chance to address those problems before it takes down their work.</li> <li>GitHub is establishing a $1 million legal defense fund for developers.</li> <li>Sidebar: EFF has just launched <a href="https://www.eff.org/deeplinks/2020/11/introducing-how-fix-internet-new-podcast-eff"><em>How to Fix the Internet</em></a>, a new podcast mini-series that examines potential solutions to six ills facing the modern digital landscape.</li> </ul> <p><strong>Brian #4:</strong> <a href="https://developer.mongodb.com/how-to/mongodb-on-raspberry-pi"><strong>Install &amp; Configure MongoDB on the Raspberry Pi</strong></a></p> <ul> <li>Mark Smith</li> <li>Definitely a “wow, I didn’t know you could do that” article.</li> <li>Tutorial walks through <ul> <li>Installing 64 bit Ubuntu Server on a Raspberry Pi</li> <li>Configure wifi</li> <li>Install MongoDB on Pi</li> <li>Set up a user account, to safely expose MongoDB on a home network.</li> <li>Now you’ve got a MongoDB server in your house. So cool</li> </ul></li> </ul> <p><strong>Michael #5: Extra! extra! extra!, hear all about it!</strong></p> <ul> <li><a href="https://twitter.com/jmnickerson/status/1327640465102016515">Follow up</a> on my critique of things like SQL &amp; CSS put next to Python and Java. Maybe best to grab the conversation from <a href="https://twitter.com/mkennedy/status/1328029407752065025">here</a>.</li> <li>Guido joins Microsoft, <a href="https://twitter.com/gvanrossum/status/1326932991566700549">why</a>? People seem to see this as a positive for sure. But they <a href="https://twitter.com/edxplore/status/1327420845031972866">checked him out</a>!</li> <li>New code editor roaming the streets: <a href="https://www.nova.app/">Nova</a> from Panic.</li> <li>Two thumbs up on Big Sur and now waiting on the Mac Mini M1.</li> </ul> <p><strong>Brian #6:</strong> <a href="https://daleonai.com/social-media-fashion-ai"><strong>A Python driven AI Stylist Inspired by Social Media</strong></a></p> <ul> <li>Dale Markowitz</li> <li>A bunch of Google tools (cloud storage, firebase, cloud vision api, product search api)</li> <li>Some React for front end</li> <li>Python to batch script</li> <li>General oversimplified process: <ul> <li>photos from social media for inspiration</li> <li>photos of everything in your closet, multiple of each item</li> <li>use AI suggest outfits from your closet that match inspiration photos</li> </ul></li> <li>Ok. The process is really more of a promo for Google AI products, and not so much about Python, but it’s a cool “look what you can do with software” kinda thing.</li> <li>Also, many of the tools used by online retail, like “similar products” and such, are available to lots of people now, and that’s cool.</li> </ul> <p>Joke:</p> <p><a href="https://devhumor.com/media/commitstrip-never-lose-hope">Back to the [dev] future!</a></p> <p><img src="https://devhumor.com/content/uploads/images/November2020/ie-linux.jpg" alt="[commitstrip] Never lose hope" /></p>

November 27, 2020 08:00 AM UTC


Brett Cannon

Unravelling `not` in Python

For this next blog post in my series of Python's syntactic sugar, I'm tackling what would seem to be a very simple bit of syntax, but which actually requires diving into multiple layers to fully implement: not.

On the surface, the definition of not is very straightforward:

The operator not yields True if its argument is false, False otherwise.

That seems simple enough, right? But when you begin to dive into what is "true" or "false" – sometimes called "truthy" and "falsey", respectively – you quickly discover that there's a decent amount that goes into that definition.

(As with the other posts in this series, the C code is for those who want to follow all the breadcrumbs, but you can feel free to skip it if you want.)

The implementation of not

Looking at the bytecode, you notice there's a single opcode dedicated to not called UNARY_NOT.

>>> import dis
>>> def spam(): not a
... 
>>> dis.dis(spam)
  1           0 LOAD_GLOBAL              0 (a)
              2 UNARY_NOT
              4 POP_TOP
              6 LOAD_CONST               0 (None)
              8 RETURN_VALUE
Bytecode for not a

The implementation of UNARY_NOT essentially calls a C function called PyObject_IsTrue() and returns the inverse of the return value: True for False, False for True.

        case TARGET(UNARY_NOT): {
            PyObject *value = TOP();
            int err = PyObject_IsTrue(value);
            Py_DECREF(value);
            if (err == 0) {
                Py_INCREF(Py_True);
                SET_TOP(Py_True);
                DISPATCH();
            }
            else if (err > 0) {
                Py_INCREF(Py_False);
                SET_TOP(Py_False);
                DISPATCH();
            }
            STACK_SHRINK(1);
            goto error;
        }
Implementation of the UNARY_NOT opcode from Python/ceval.c

Defining what is true

The trickiness with unravelling not starts with defining what is true. Looking at the C implementation of PyObject_IsTrue(), you see there are a few possible ways to figure out the truth of an object.

/* Test a value used as condition, e.g., in a for or if statement.
   Return -1 if an error occurred */


int
PyObject_IsTrue(PyObject *v)
{
    Py_ssize_t res;
    if (v == Py_True)
        return 1;
    if (v == Py_False)
        return 0;
    if (v == Py_None)
        return 0;
    else if (v->ob_type->tp_as_number != NULL &&
             v->ob_type->tp_as_number->nb_bool != NULL)
        res = (*v->ob_type->tp_as_number->nb_bool)(v);
    else if (v->ob_type->tp_as_mapping != NULL &&
             v->ob_type->tp_as_mapping->mp_length != NULL)
        res = (*v->ob_type->tp_as_mapping->mp_length)(v);
    else if (v->ob_type->tp_as_sequence != NULL &&
             v->ob_type->tp_as_sequence->sq_length != NULL)
        res = (*v->ob_type->tp_as_sequence->sq_length)(v);
    else
        return 1;
    /* if it is negative, it should be either -1 or -2 */
    return (res > 0) ? 1 : Py_SAFE_DOWNCAST(res, Py_ssize_t, int);
}
Implementation of PyObject_IsTrue()

When you look at the C implementation, the rule seems to be:

  1. If True, then True
  2. If False, then False
  3. If None, then False
  4. Whatever __bool__ returns as long as it's a subclass of bool (that's what calling nb_bool represents)
  5. Calling len() on the object (that's what calling mp_length and sq_length represent):
    1. Greater than 0, then True
    2. Otherwise False
  6. If none of the above applies, then True

Rules 1 through 3 and 6 are straight-forward, rules 4 and 5 require going deeper into detail.

__bool__

The definition of the special/magic method __bool__ basically says that the method is used "to implement truth value testing" and should return True or False. Pretty simple.

len()

The built-in len() function returns an integer representing how many items are in a container. The implementation of calculating an object's length is represented by the sq_length slot (length of sequences) and the mp_length slot (length of dicts/maps).

You might think it would be a simple thing to ask an object to tell you its length, but it turns out there are two layers to this.

__len__

The first layer is the special/magic method __len__. As you might expect, it "should return the length of the object, an integer >= 0". But the wrinkle here is that "integer" doesn't mean int, but actually an object that you can "losslessly convert ... to an integer object". So how do you do that sort of conversion?

__index__

"To losslessly convert the numeric object to an integer object", you use the __index__ special/magic method. Specifically, the PyNumber_Index() function is used to handle the conversion. The function is a little too long to bother pasting in here, but what it does is:

  1. If the argument is an instance of int, return it
  2. Otherwise, call __index__ on the object
  3. If __index__ returns an exact instance of int, return it (technically returning a subclass is only deprecated, but let's leave the old ways behind us 😉)
  4. Otherwise raise TypeError

At the Python level this is exposed via operator.index(). Unfortunately it doesn't implement PyNumber_Index() semantics, so it's actually inaccurate from the perspective of not and len(). If it were to implement those semantics, it would look like:

def index(obj: Object, /) -> int:
    """Losslessly convert an object to an integer object.

    If obj is an instance of int, return it directly. Otherwise call __index__()
    and require it be a direct instance of int (raising TypeError if it isn't).
    """
    # https://github.com/python/cpython/blob/v3.8.3/Objects/abstract.c#L1260-L1302
    if isinstance(obj, int):
        return obj

    length_type = builtins.type(obj)
    try:
        __index__ = _mro_getattr(length_type, "__index__")
    except AttributeError:
        msg = (
            f"{length_type!r} cannot be interpreted as an integer "
            "(must be either a subclass of 'int' or have an __index__() method)"
        )
        raise TypeError(msg)
    index = __index__(obj)
    # Returning a subclass of int is deprecated in CPython.
    if index.__class__ is int:
        return index
    else:
        raise TypeError(
            f"the __index__() method of {length_type!r} returned an object of "
            f"type {builtins.type(index).__name__!r}, not 'int'"
        )
Python implementation of PyNumber_Index()

len() implementation

One interesting thing about the implementation of len() is that it always returns an exact int. So while __index__() or __len__() could return a subclass, the way it's implemented at the C level using PyLong_FromSsize_t() guarantees that a direct int instance will always be returned.

Otherwise len() does some basic sanity checks about what __len__() and __index__() return such as being a subclass of int, being greater or equal to 0, etc. As such, you can implement len() as:

def len(obj: Object, /) -> int:
    """Return the number of items in a container."""
    # https://github.com/python/cpython/blob/v3.8.3/Python/bltinmodule.c#L1536-L1557
    # https://github.com/python/cpython/blob/v3.8.3/Objects/abstract.c#L45-L63
    # https://github.com/python/cpython/blob/v3.8.3/Objects/typeobject.c#L6184-L6209
    type_ = builtins.type(obj)
    try:
        __len__ = _mro_getattr(type_, "__len__")
    except AttributeError:
        raise TypeError(f"type {type!r} does not have a __len__() method")
    length = __len__(obj)
    # Due to len() using PyObject_Size() (which returns Py_ssize_t),
    # the returned value is always a direct instance of int via
    # PyLong_FromSsize_t().
    index = int(_index(length))
    if index < 0:
        raise ValueError("__len__() should return >= 0")
    else:
        return index

Implementing operator.truth()

In a lot of programming languages that define the not operation, it's a common idiom to turn an object into its comparitive boolean value by passing it to not twice via not not: once to get the inverted boolean value, and the second time to invert the inversion to get the boolean value that you originally wanted.

In Python we don't need this idiom. Thanks to bool() (and specifically bool.__new__()), we have a function call that we can use to get the boolean value; it's exposed via operator.truth(). And if you look at that method you will discover it uses PyObject_IsTrue() to determine the boolean value for an object. Looking at slot_nb_bool, you will see that it ends up doing what PyObject_IsTrue() does. What all of this means is that if we can implement the analogue of PyObject_IsTrue() then we can determine what boolean value an object represents.

Using the outline from earlier and what we have covered up until now, we can implement operator.truth() for this logic (I'm choosing not to implement bool because I don't want to have to implement all of its numeric functions and I have not come up with a good way to make True and False from scratch that inherit from 1 and 0, respectively, in pure Python):

def truth(obj: Any, /) -> bool:
    """Return True if the object is true, False otherwise.

    Analogous to calling bool().

    """
    if obj is True:
        return True
    elif obj is False:
        return False
    elif obj is None:
        return False
    obj_type = type(obj)
    try:
        __bool__ = debuiltins._mro_getattr(obj_type, "__bool__")
    except AttributeError:
        # Only try calling len() if it makes sense.
        try:
            __len__ = debuiltins._mro_getattr(obj_type, "__len__")
        except AttributeError:
            # If all else fails...
            return True
        else:
            return True if debuiltins.len(obj) > 0 else False
    else:
        boolean = __bool__(obj)
        if isinstance(boolean, bool):
            # Coerce into True or False.
            return truth(boolean)
        else:
            raise TypeError(
                f"expected a 'bool' from {obj_type.__name__}.__bool__(), "
                f"not {type(boolean).__name__!r}"
            )
Implementation of operator.truth()

Implementing not

With operator.truth() implemented, getting operator.not_() to work is just lambda a, /: False if truth(a) else True. The end result is simple, but getting here took a bit of work. 😉

As always, the code in this post can be found in my desugar project.

November 27, 2020 03:41 AM UTC


Daniel Bader

Function and Method Overloading in Python

Function and Method Overloading in Python

How to “overload” your methods and functions in Python so they can be called with different sets of parameters.

When writing a Python program, sometimes it’s nice to be able to create a function or method that allows you to blindly call it no matter what sort of parameter you’re feeding it.

For example, if you’re writing code that will calculate the volumes of different solids, there are two basic ways you could do this.

The first would be to write a method for each type of solid, like so:

Each method would take in some set of args or parameters and return the appropriate value.

The second way to do it would be to create a series of methods simply called volume(args) and change the type of parameters each method took. For example,

Each of these would accept different arguments based on how you called them.

The problem with the first technique is that before you can call the appropriate method, you have to determine which method you have to call.

In the second, you’ve “overloaded” the method so that depending on what parameters you send, the code knows which method to call.

In this tutorial you’ll learn how to overload methods and functions in Python. Because this technique works slightly differently in Python compared to other popular programming languages like C++, C#, or Java, we’ll spend some time going over these differences first.

This should make it easier for you to transfer these concepts if your switching to Python from a different programming language background.

Let’s get started!

What Exactly Is Method or Function Overloading?

Overloading a method or a function is one of the hallmarks of some object oriented programming (OOP) languages, like C#, C++, and Java. It allows you to forgo having to name each specific method something different. As the same method name is used with each call, each overloaded function has to differ in the parameters that are sent.

This can be a difference in the arity—that is, the number of parameters. It can also be a difference in the data types, or a difference in the order of the data types. That is, a method called with the parameters (int, long) is overloading one using the call (long, int).

As you can see in the three volume methods above, each overloaded method calls a different combination of an integer and a long data type. I’m always a fan of showing real code examples when discussing programming topics, so let’s take a look at how a statically typed language like C++ handles this task.

Here’s how you’d implement these three overloaded functions in C++ (don’t worry, we’ll switch to Python in a minute):

// Returns cube volume
int volume(int side) {
     return side * side * side;
}

// Volume of sphere
float volume(float radius) {
     return (4.0 / 3.0) * 3.14159265 * radius * radius * radius;
}

// Returns cylinder volume
float volume(int height, float radius) {
     return static_cast<float>(height) * radius * radius * 3.14159265;
}

The program to use these methods could then calculate the volume of a cylinder by calling volume(4, 1.2), or the volume of a sphere by calling volume(2.3):

#include <stdio.h>

int main() {
    printf("Cube volume: %f", volume(5));
    printf("Sphere volume: %f", volume(2.3));
    printf("Cylinder volume: %f", volume(4, 1.2));
    return 0;
}

Why Overload Your Methods?

The reason that overloading is desirable is because it makes your code cleaner and easier to read. Consider these overloaded methods for the Java Math class:

static double max(double a, double b)
static float max(float a, float b)
static int max(int a, int b)
static long max (long a, long b)

These overloaded implementations of the max method return the greater of the two values passed to them. Without overloading, the methods would look like this:

static double maxDouble(double a, double b)
static float maxFloat(float a, float b)
static int maxInt(int a, int b)
static long maxLong(long a, long b)

The non-overloaded methods are harder to read and don’t look as sharp as the overloaded methods. And remember the first line of The Zen of Python:

“Beautiful is better than ugly.”

And nestled somewhere in there is the second adage:

“Readability counts.”

So, How to Overload a Method in Python

The way to overload a method or function in Python depends on if you’re coding in Python 2.x or Python 3.x. Each has its own specific way to do it. See, for some reason, Python doesn’t include overloading in its library in the way that Java or C++ does. For example, here’s a bit of Python code that looks like it should overload a basic method:

def add_stuff(a, b):
    return a + b

def add_stuff(a, b, c):
    return a + b + c

print add_stuff(1, 2)

That looks like it should return 3, right? Well, no. If you run that code, you’ll get a TypeError exception:

TypeError: add_stuff() takes exactly 3 arguments (2 given).

That’s because methods and functions in Python are limited to one function signature per name. As soon as you define a new method in the code using the same name, Python will take that method and its parameters as the definition to replace the previous one.

Overloading Methods in Python 2.7

Python users in 2.7 learned to code a makeshift method to code an overloaded function by using nested conditional statements.

def addStuff(parameter, *args):
    if parameter == 'int':
        result = 0
    if parameter == 'str':
        result = ' '
    for i in args:
        result = result + i
        return result

If you call the add method by using the following code:

print addStuff('int', 1,2,3)
print addStuff('str', 'this', ' works')

then you will get the following output of

6
this works

The problem with this style of overloading a method in Python is that it violates those two tenets. It’s not very pretty and it certainly doesn’t enhance the readability of the code. Imagine if you wanted to overload six methods. You’d have a huge long method with a tangle of nested conditionals that would be annoying to try to debug. Not to mention the hassle of changing the code if you needed to add in how addStuff would handle a long or a double data type.

Thankfully, the Python developers listened and along came a sweeping change to how method overloading would work in Python 3.

Single Dispatch Method Overloading in Python 3

Python 3 added support for method overloading by adding something called single dispatch to the existing functools standard library module.

Developers recognized that Python didn’t have a way for programmers to write generic functions like other languages, and that in order to do so, everyone was coming up with their own way to do it. Some were defining __special__ methods, and others were monkey patching (replacing existing attributes of classes while the program is running. This can be done because Python’s classes are all mutable).

The Python dev team realized that the existing type inspection for methods wasn’t going to work, so they developed the @singledispatch decorator. In doing so, they established a uniform API that allowed coders everywhere to start making overloaded methods that were pretty, functional and readable.

The way that singledispatch works in Python is this. It allows you to make a generic method that acts as the default method when you make the rest of your overloaded methods. You call singledispatch on the first method.

Once you’ve done that, any overloaded methods use the register() attribute of the first generic method. This decorator takes a specific data type as a parameter and implements the method for that specific type.

Using our addStuff example method, overloading it in Python 3 using singledispatch then looks like this:

from functools import singledispatch
@singledispatch

def addStuff(a, b):
    return a + b

@addStuff.register(float)
def _(a, b, c):
    return a + b + c

@addStuff.register(str)
def _(a, b, c, d):
    return a + b + c + d

The first method accepts a default argument that isn’t a float or a string. The best part about this is you can send it anything that isn’t defined in the overloaded methods. This includes complex, int, or even arrays or tuples.

For example, if you call the methods by using the following calls:

print (addStuff((1, 2, 3), (3, 4, 5)))
print (addStuff(1.0, 2.1, 3.0))
print (addStuff('this', ' is', ' python', ' fun!'))

the output will be the following:

(1, 2, 3, 3, 4, 5)
6.1
this is python fun!

If you need to check what data types your single dispatch methods will use, you can do that by using the following console command

addStuff.registry.keys()

This is a read only attribute that will check and return the dict_keys that are used in these methods. For our addStuff methods, the returned information is:

dict_keys([<class 'object'>, <class 'float'>, <class 'str'>])

That lets you know that the first (and default generic) method will accept any object or data type. The second takes floats and the last takes strings. This is a great way to find out if you’ve already accounted for a specific data type.

Multiple Dispatch for Python

Single dispatch is great when you’re dealing with one data type outside of an arbitrarily determined class. However, real life code is never that easy. Consider our method addStuff. The method that is invoked is determined by the type of object – float, string, or a generic type.

This type of method calling is great until you need to determine how two objects will interact. Consider how a cat reacts to a mouse, a dog, or another cat. The cat’s actions are dependent not only on it being a cat, but also based on what animal it sees. In Python (or any other language), single dispatch won’t be able to handle this.

That’s where multiple dispatch mechanisms come in as a way of overloading a method. What essentially happens is that there are two method calls: one determines whether what the first animal is. The second determines what type of animal that one is seeing. This is more precisely called a double dispatch, but you should see how multiple dispatch extends past this. Your program is going to make multiple method calls to determine the object types involved and then use a polymorphic method call for each.

Python does not include native multiple dispatch support. However, there is a library extension called multimethods.py that allows you to use multiple dispatch support. Using our cat, dog, and mouse example, this is how overloading methods would take place using multiple dispatch

This assumes that we’ve written a class named Animal that defines the objects Cat, Mouse, and Dog as well as a class named Interactions that determines the interactions of each, i.e. CatMouse, MouseCat, CatDog, DogCat, etc.

from multimethods import Dispatch
from animal import Cat, Mouse, Dog
from interactions import (
    CatMouse, MouseCat, CatDog, DogCat, DogMouse,
    MouseDog, CatCat, DogDog, MouseMouse)

reaction = Dispatch()
reaction.add_rule((Cat, Mouse), CatMouse)
reaction.add_rule((Cat, Dog), CatDog)
# etc.

Then you can call the reaction by using the call:

reaction(a, b)

This can also be done using Python 2.7 decorators, as Guido Van Rossum (the Benevolent Dictator For Life of Python) showed.

@multimethod(Cat, Dog)
def reaction(a, b):
    """Interaction when cat sees dog"""
    # defines a new behavior

@multimethod(Dog, Cat)
def reaction(a,b):
    """Interaction when cat sees dog"""
    # defines a new behavior

After all of the reactions are defined, you can define the multimethod decorator through a monkey patch. Van Rossum shows how this can be done in his 2005 article here.

It’s one of Python’s strengths that both multiple dispatch and single dispatch can be extended in the language so simply. This lets you code in overloaded methods no matter which version of the language you’re using.


[ Improve Your Python with Dan's 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

November 27, 2020 12:00 AM UTC

November 26, 2020


PyCharm

PyCharm 2020.2.4 is out!

The new bug-fix release is out! Check out the latest improvements in PyCharm 2020.2.4.

You can upgrade to this new version from the IDE, with the Toolbox App, or using snaps if you are an Ubuntu user. It is also available for download from our website.

Here is a collection of the most notable updates:

The JetBrains Runtime is now based on OpenJDK 11.0.9. We’ve updated JBR 11 to 11.0.9+11-b944.49 with the following improvements:

You can find the full list of changes in the release notes. If you have any suggestions or concerns, please post them to our issue tracker or leave a comment on this blog post.

Happy developing!

November 26, 2020 09:50 PM UTC


Stack Abuse

Matplotlib Histogram Plot - Tutorial and Examples

Introduction

Matplotlib is one of the most widely used data visualization libraries in Python. From simple to complex visualizations, it's the go-to library for most.

In this tutorial, we'll take a look at how to plot a histogram plot in Matplotlib. Histogram plots are a great way to visualize distributions of data - In a histogram, each bar groups numbers into ranges. Taller bars show that more data falls in that range.

A histogram displays the shape and spread of continuous sample data.

Import Data

We'll be using the Netflix Shows dataset and visualizing the distributions from there.

Let's import Pandas and load in the dataset:

import pandas as pd

df = pd.read_csv('netflix_titles.csv')

Plot a Histogram Plot in Matplotlib

Now, with the dataset loaded in, let's import Matplotlib's PyPlot module and visualize the distribution of release_years of the shows that are live on Netflix:

import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('netflix_titles.csv')
plt.hist(df['release_year'])

plt.show()

Here, we've got a minimum-setup scenario. We load in the data into a DataFrame (df), then, we use the PyPlot instance and call the hist() function to plot a histogram for the release_year feature. By default, this'll count the number of occurences of these years, populate bars in ranges and plot the histogram.

Running this code results in:

matplotlib simple histogram plot tutorial

Here, the movie bins (ranges) are set to 10 years. Each bar here includes all shows/movies in batches of 10 years. For example, we can see that around ~750 shows were released between 2000. and 2010. At the same time, ~5000 were released between 2010. and 2020.

These are pretty big ranges for the movie industry, it makes more sense to visualize this for ranges smaller than 10 years.

Change Histogram Bin Size in Matplotlib

Say, let's visualize a histogram (distribution) plot in batches of 1 year, since this is a much more realistic time-frame for movie and show releases.

We'll import numpy, as it'll help us calculate the size of the bins:

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

df = pd.read_csv('netflix_titles.csv')
data = df['release_year']

plt.hist(data, bins = np.arange(min(data), max(data) + 1, 1))

plt.show()

This time around, we've extracted the DataFrame column into a data variable, just to make it a bit easier to work with.

We've passed the data to the hist() function, and set the bins argument. It accepts a list, which you can set manually, if you'd like, especially if you want a non-uniform bin distribution.

Since we'd like to pool these entries each in the same time-span (1 year), we'll create a Numpy array, that starts with the lowest value (min(data)), ends at the highest value (max(data)) and goes in increments of 1.

This time around, running this code results in:

change histogram bin size in matplolib

Instead of a list, you can give a single bins value. This will be the total number of bins in the plot. Using 1 will result in 1 bar for the entire plot.

Say, we want to have 20 bins, we'd use:

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

df = pd.read_csv('netflix_titles.csv')
data = df['release_year']

plt.hist(data, bins = 20)

plt.show()

This results in 20 equal bins, with data within those bins pooled and visualized in their respective bars:

change hisogram bin size uniformly in matplotlib

This results in 5-year intervals, considering we've got ~100 years worth of data. Splitting it up in 20 bins means that each will include 5 years worth of data.

Plot Histogram with Density

Sometimes, instead of the count of the features, we'd want to check what the density of each bar/bin is. That is, how common it is to see a range within a given dataset. Since we're working with 1-year intervals, this'll result in the probablity that a movie/show was released in that year.

To do this, we can simply set the density argument to True:

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

df = pd.read_csv('netflix_titles.csv')
data = df['release_year']
bins = np.arange(min(data), max(data) + 1, 1)

plt.hist(data, bins = bins, density = True)
plt.ylabel('Density')
plt.xlabel('Year')

plt.show()

Now, instead of the count we've seen before, we'll be presented with the density of entries:

histogram plot with density matplotlib

We can see that ~18% of the entries were released in 2018, followed by ~14% in 2019.

Customizing Histogram Plots in Matplotlib

Other than these settings, there's a plethora of various arguments you can set to customize and change the way your plot looks like. Let's change a few of the common options people like to fiddle around with to change plots to their tastes:

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

df = pd.read_csv('netflix_titles.csv')
data = df['release_year']
bins = np.arange(min(data), max(data) + 1, 1)

plt.hist(data, bins = bins, density = True, histtype = 'step', alpha = 0.5, align = 'right', orientation = 'horizontal', log = True)

plt.show()

Here, we've set various arguments:

This now results in:

customize matplotlib histogram

Since we've put the align to right, we can see that the bar is offset a bit, to the vertical right of the 2020 bin.

Conclusion

In this tutorial, we've gone over several ways to plot a histogram plot using Matplotlib and Python.

If you're interested in Data Visualization and don't know where to start, make sure to check out our book on Data Visualization in Python.

Data Visualization in Python, a book for beginner to intermediate Python developers, will guide you through simple data manipulation with Pandas, cover core plotting libraries like Matplotlib and Seaborn, and show you how to take advantage of declarative and experimental libraries like Altair.

Data Visualization in Python

Understand your data better with visualizations! With over 275+ pages, you'll learn the ins and outs of visualizing data in Python with popular libraries like Matplotlib, Seaborn, Bokeh, and more.

November 26, 2020 02:30 PM UTC

How to Check if List is Empty in Python

Introduction

Lists are one of the four most commonly used data structures provided by Python. Its functionality, extensibility, and ease of use make it useful for implementing various types of functionalities.

Python lists have a few interesting characteristics:

  1. Mutability - meaning it can change, which means it allows us to easily add and delete entries from it. This is the main difference between Python lists and tuples
  2. Iterability - which means we can iterate through it (go through all elements in the list in-order)

The main attribute that will be focusing on is Iterability. An important part when dealing with an iterable object, in this case a list, is checking if there's anything to iterate through. If not handled properly, this can lead to a lot of unwanted errors.

Python provides various ways to check if our list is empty or not, some implicit and some explicit, and in this article, we'll go over how to check if a Python list is empty.

Using len() Function

One of the techniques is to use the len() function to check if our list is empty or not:

py_list = []

"""
Here len() returns 0, which is 
implicitly converted to false
"""

if len(py_list):
	print('The list is not empty')
else:
	print('T list is empty')

Output

List is empty

When len(py_list) executes it produces zero, which is then implicitly cast to the boolean value of False. Thus in case of an empty list the program will be redirected to the else block.

Although this method looks simple, it's not that intuitive for beginners.

Using len() With Comparison Operator

This technique is similar to the one above but it is more explicit and easy to understand. That's why those who are new to python or coding itself usually consider it more intuitive:

if len(py_list) == 0:
	print('List is empty')
else:
	print('List not empty')

In the code above, len(py_list) == 0 will be true if the list is empty and will will be redirected to the else block. This also allows you to set other values as well, rather than relying on 0 being converted as False. All other positive values are converted to True.

Comparison With Empty List

This method is also very simple and works well for beginners as it involves comparing with an empty list:

if py_list == []:
	print('List is empty')
else:
	print('List is not empty')

Here again, we are using the comparison operation to compare one list with another - am empty one, and if both are empty the if block will execute.

Pep-8 Recommended Style

#PEP-8 recommended style

if py_list:
	print('List is not empty')
if not py_list:
	print('List empty')

For this, let's take a look at Truth Value Testing. The official docs state that:

Here are most of the built-in objects considered false:

  • constants defined to be false: None and False.
  • zero of any numeric type: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
  • empty sequences and collections: '', (), [], {}, set(), range(0)

As an empty list is in fact just a empty collection, it will be converted to a boolean value of False. Therefore, if py_list is empty, it will converted to False.

The second statement is pretty similar, except not will invert the a false condition to a true one. This approach is very similar to the if(len(list)) approach.

This is the preferred approach as it's the cleanest and shortest solution there is.

Using bool() Function

We can also use the bool() function to verify a list is empty:

#As truth value testing says [] braces denotes false

if bool(py_list):
	print('List is not empty')
else:
	print('List is empty')

This is basically a manually implemented truth value test. So if the list is not empty the function will return True and if block will be executed.

This approach is less common as we can achieve the desired results even without using bool(), but it's not a bad thing to know how Python works under the hood.

Conclusion

This article was all about ways to check if our python list is empty or not. We started by exploring different techniques and finally looking into some parameters that we can use to make our judgment regarding which technique may work for us.

I can't say that this is the end as new Python updates may give rise to new and more improved coding styles. So it's better to keep exploring and keep learning.

November 26, 2020 01:30 PM UTC


Talk Python to Me

#292 Pythonic identity (auth in Python ecosystem)

So you're excited about that next app you're about to build. You can visualize the APIs with the smooth scalability taking to the mobile apps. You can see how, finally, this time, you'll get deployment right and it'll be pure continuous delivery out of GitHub with zero downtime. <br/> <br/> What you're probably not dreaming about is writing yet another password reset form and integrating mail capabilities just for this purpose. Or how you'll securely store user accounts the right way this time. <br/> <br/> Don't worry, we got you covered. Our guests, Christos Matskas and John Patrick Dandison are here to cover a bunch of different libraries and techniques we can use for adding identity to our Python applications.<br/> <br/> <strong>Links from the show</strong><br/> <br/> <div><b>Christos on Twitter</b>: <a href="https://twitter.com/christosmatskas" target="_blank" rel="noopener">@christosmatskas</a><br/> <b>John Patrick Dandison on Twitter</b>: <a href="https://twitter.com/azureandchill" target="_blank" rel="noopener">@azureandchill</a><br/> <br/> <b>shhgit live</b>: <a href="https://www.shhgit.com/" target="_blank" rel="noopener">shhgit.com</a><br/> <b>Twitch channel for Christos and JP</b>: <a href="https://www.twitch.tv/425show" target="_blank" rel="noopener">twitch.tv/425show</a><br/> <br/> <b>Passlib & Folding</b>: <a href="https://passlib.readthedocs.io/en/stable/narr/hash-tutorial.html#choosing-the-right-rounds-value" target="_blank" rel="noopener">passlib.readthedocs.io</a><br/> <b>Microsoft Authentication Library</b>: <a href="https://github.com/AzureAD/microsoft-authentication-library-for-python" target="_blank" rel="noopener">github.com/AzureAD</a><br/> <b>authlib - JavaScript Object Signing and Encryption draft implementation</b>: <a href="https://github.com/lepture/authlib" target="_blank" rel="noopener">github.com</a><br/> <b>django-allauth - Authentication app for Django that "just works"</b>: <a href="https://github.com/pennersr/django-allauth" target="_blank" rel="noopener">github.com</a><br/> <b>django-oauth-toolkit - OAuth 2 goodies for Django</b>: <a href="https://github.com/evonove/django-oauth-toolkit" target="_blank" rel="noopener">github.com</a><br/> <b>python-oauth2 - A fully tested, abstract interface to creating OAuth clients and servers</b>: <a href="https://github.com/joestump/python-oauth2" target="_blank" rel="noopener">github.com</a><br/> <b>python-social-auth - An easy-to-setup social authentication mechanism</b>: <a href="https://github.com/omab/python-social-auth" target="_blank" rel="noopener">github.com</a><br/></div><br/> <strong>Sponsors</strong><br/> <br/> <a href='https://talkpython.fm/training'>Talk Python Training</a><br> <a href='https://talkpython.fm/linode'>Linode</a>

November 26, 2020 08:00 AM UTC

November 25, 2020


Trey Hunner

Short weekly Python screencasts for $50/year

I’m offering a service to help life-long Python learners manufacture ah-ha moments.

A few years ago at my local Python meetup I was discussing how function arguments work (they’re call-by-assignment a.k.a. call by object). A friend spoke up to clarify: “but it doesn’t work that way for numbers and strings, right?” I said “I’m pretty sure it works like this for everything”.

After some quiet Googling, my friend declared “I’ve been using Python for over a decade and I never knew it worked this way”. They’d suddenly realized their mental model of the Python world differed from Python’s model of itself. They’d experienced an “ah-ha moment”.

I’m going to publish at least one short Python screencast every week to help manufacture Python ah-ha moments. These will be single-topic screencasts that won’t waste your time.

So, if you’re a life-long learner who uses Python and doesn’t have a wealth of time for learning, read on.

What is this?

With this subscription you’ll receive access to a growing archive of Python screencasts (at least one new screencast each week). If you enjoy my articles or my talks and tutorials, you’ll probably enjoy the format I use in my screencasts.

Don’t like video? That’s okay! Each screencast is captioned and includes a mini-blog post which is nearly a text-based equivalent to the video.

What are the screencasts like?

Each screencast will be concise and short, under 6 minutes. Examples include variables are pointers (2 mins) and the 2 types of “change” (3 mins), plus others here.

What topics will the screencasts be on? Functions, classes, scope, operator overloading, decorators, exception handling, and more. Screencasts will focus on Python core, not third-party libraries (no Pandas, Numpy, or Django). Topics will range from beginner to advanced.

Will the screencasts be freely shareable? Some screencasts will be limited to subscribers and some will be available to non-subscribers, with a yet-to-be-decided breakdown between the two.

You’ll also get get occasional Python exercises

This weekly screencast subscription is part of Python Morsels, an exercise subscription service I run. In addition to weekly screencasts, you’ll also get one Python exercise each month.

If you’ve taken my PyCon tutorials or attended my trainings, you know exercises are the best part of my curriculum. I spend a lot of time making new exercises because we learn by attempting to retrieve information from our heads (through practice), not by putting information into our heads.

Python Morsels exercises are both interesting and complex but not complicated. You don’t need to work through the monthly exercises, but I do recommend it.

This subscription is $50/year for a limited time

I’m offering this service for a comparatively low price of $50/year because I don’t have a large archive of screencasts yet. I have plans to increase the price in 2021, but as an early user your price will always be $50/year.

If you’re not sure whether this is for you, sign up to try it out for free.

Why pay for this when there’s a lot of great free Python videos out there?

Why am I charging money for this?

There’s really one reason: you’re trading money for time. This is a tradeoff I’ve grown an appreciation for (one which would baffle a younger version of myself).

This time-money tradeoff comes in a few forms:

  1. You will never see any ads on Python Morsels: you’re not the product, the screencasts are
  2. No filler content or rambling (no ad revenue means no need for long videos)
  3. I have unique expertise and perspective: teaching Python is my business and I’m good at it

Watch some of the current screencasts before signing up. If my teaching style isn’t for you, that’s okay! But if my teaching style is for you, I think you’ll find the next year’s worth of screencasts will be worthwhile! 😁

Student discounts? Team subscriptions? Other questions?

My standard discount policy is income-tiered: if you make less than $60,000 USD annually, you’re eligible. I also offer situation-specific discounts, so please ask for a discount if you need one.

If you’re paying through your employer, note that there are team subscriptions too. Just fill out this form to get started setting up a subscription for your team.

Ready to try it out?

Are you ready to subscribe to a growing collection of short and concise Python screencasts? Let’s get learning!

Do you have another question that I haven’t answered here? Check out the Lite plan FAQ or email your question to help@pythonmorsels.com.

Happy learning!

November 25, 2020 05:00 PM UTC


PyCharm

Webinar Recording: “What It’s Like To Do Instructional Videos on YouTube” with Nelson Jamal

Learning new things is part and parcel of a developer’s job. Many coders, including both novices and pros, turn to videos to help them understand the basics of a programming language or grasp complex concepts. If you’d like to know how to create helpful learning videos for developers, watch the recording of this webinar hosted by Paul Everitt, PyCharm Developer Advocate, and Nelson Jamal, YouTube blogger and the creator of AmigosCode YouTube channel.

The webinar covers a lot of ground, including:

The audience asked lots of useful questions, so thanks to all the PyCharmers who participated and helped.

Feel free to comment on YouTube (under the webinar recording) what you think of the revamped format of the PyCharm webinars, and like the video so we know that you want more YouTube broadcasts. If you have questions for Nelson, here’s where to find him:

November 25, 2020 04:19 PM UTC


Python Morsels

Slicing


Transcript

You can slice pretty much any sequence in Python. A sequence is something that you can index from 0 to len(sequence)-1. Lists, tuples, and strings are all examples of sequences.

Let say we have a variable fruits that points to a list:

>>> fruits = ['watermelon', 'apple', 'lime', 'kiwi', 'pear', 'lemon', 'orange']
>>> fruits
['watermelon', 'apple', 'lime', 'kiwi', 'pear', 'lemon', 'orange']

We can get an item from this list by indexing it:

>>> fruits[3]
'kiwi'

Slicing basics

If we put a colon and another number inside the square brackets, we're slicing this list instead of indexing it:

>>> fruits[0:3]
['watermelon', 'apple', 'lime']

Slicing a list gives us back a new list. We're getting a list of the first three items here.

What do you think we'll get if we slice using 1 and 3 instead of 0 and 3?

>>> fruits[1:3]
['apple', 'lime']

We only get 2 items this time instead of 3.

In slicing, the first item is the start index and the second is the stop index. We stop just before the stop index. So we're getting the items at index 1 and 2 here (we stop just before 3).

The start index is inclusive and the stop index is exclusive (we stop just before it).

Default start/stop values

The start and stop values are both optional. The start value defaults to 0:

>>> fruits[:3]
['watermelon', 'apple', 'lime']

The stop value defaults to the end of the list:

>>> fruits[1:]
['apple', 'lime', 'kiwi', 'pear', 'lemon', 'orange']

The exclusivity of the stop index has a nice side effect: if you slice up to index 3 and then start slicing again from 3 onward, and add those two slices together we'll get back a cop of our original list:

>>> fruits[:3] + fruits[3:]
['watermelon', 'apple', 'lime', 'kiwi', 'pear', 'lemon', 'orange']

This happens because the stop value is always exclusive and start values is always inclusive.

Out-of-bounds slicing is allowed

Normally if you index past the end of a list, you'll get an error:

>>> fruits[15]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

But slicing past the end of the list, doesn’t raises an error. It just stops at the end of the list:

>>> fruits[:15]
['watermelon', 'apple', 'lime', 'kiwi', 'pear', 'lemon', 'orange']

The same applies to the beginning of the list.

The step value

You can actually specify third value when slicing: the step value.

The start index defaults to 0, the stop index defaults to the end of the list, and the optional step value, defaults to 1:

>>> fruits[::1]
['watermelon', 'apple', 'lime', 'kiwi', 'pear', 'lemon', 'orange']

If we change the step value to 2, we'll skip every other item:

>>> fruits[::2]
['watermelon', 'lime', 'pear', 'orange']

With 3 we'll show every third item:

>>> fruits[::3]
['watermelon', 'kiwi', 'orange']

The most common step value to see is -1. This reverses the list:

>>> fruits[::-1]
['orange', 'lemon', 'pear', 'kiwi', 'lime', 'apple', 'watermelon']

Whenever a negative step value is given, the default meaning of start and stop change. The start value will now default to the length of the list and the stop value will default to just before the beginning of the list.

I don't usually use a step value with slicing. The only use I usually have for a step value is reversing a sequence and I tend to prefer using the built-in reversed function for that:

>>> list(reversed(fruits))
['orange', 'lemon', 'pear', 'kiwi', 'lime', 'apple', 'watermelon']

What's the use?

The most common uses of slicing in Python are grabbing the first few items:

>>> fruits[:2]
['watermelon', 'apple']

Or last few items:

We can index from the end of list as we do from the start of the list.

>>> fruits[-2:]
['lemon', 'orange']

You also might see slicing used to get every item but the first or last items. This returns everything but the first and last items:

>>> fruits[1:-1]
['apple', 'lime', 'kiwi', 'pear', 'lemon']

So, you can use slicing to get the last few things, or the first few things, or to get everything except for that last and first items, or for reversing your sequence. Those are the most common use cases for slicing in Python.

November 25, 2020 04:00 PM UTC


Stack Abuse

Matplotlib: Change Scatter Plot Marker Size

Introduction

Matplotlib is one of the most widely used data visualization libraries in Python. Much of Matplotlib's popularity comes from its customization options - you can tweak just about any element from its hierarchy of objects.

In this tutorial, we'll take a look at how to change the marker size in a Matplotlib scatter plot.

Import Data

We'll use the World Happiness dataset, and compare the Happiness Score against varying features to see what influences perceived happiness in the world:

import pandas as pd

df = pd.read_csv('worldHappiness2019.csv')

Then, we can easily manipulate the size of the markers used to represent entries in this dataset.

Change Marker Size in Matplotlib Scatter Plot

Let's start off by plotting the generosity score against the GDP per capita:

import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('worldHappiness2019.csv')

fig, ax = plt.subplots(figsize=(10, 6))
ax.scatter(x = df['GDP per capita'], y = df['Generosity'])
plt.xlabel("GDP per Capita")
plt.ylabel("Generosity Score")

plt.show()

This results in:

matplotlib scatter plot

Now, let's say we'd like to increase the size of each marker, based on the perceived happiness of the inhabitants of that country. The happiness score is a list, coming straight from the df, so this can work with other lists as well.

To change the size of the markers, we use the s argument, for the scatter() function. This will be the markersize argument for the plot() function:

import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('worldHappiness2019.csv')

fig, ax = plt.subplots(figsize=(10, 6))
ax.scatter(x = df['GDP per capita'], y = df['Generosity'], s = df['Score']*10)
plt.xlabel("GDP per Capita")
plt.ylabel("Generosity Score")

plt.show()

We've also multiplied the value of each element in the list by an arbitrary number of 25, because they're ranked from 0..1. This will produce really small markers if we use them in their original values.

This now results in:

matplotlib change scatter plot marker size

Or better yet, instead of crudely multiplying everything by 25, since the values are similar anyway, we can do something like this:

import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('worldHappiness2019.csv')

size = df['Score'].to_numpy()
s = [3*s**2 for s in size]

fig, ax = plt.subplots(figsize=(10, 6))
ax.scatter(x = df['GDP per capita'], y = df['Generosity'], s = s)
plt.xlabel("GDP per Capita")
plt.ylabel("Generosity Score")

plt.show()

It's important to have the s list the same length as x and y, as each value from s now gets applied to them. If the list is shorter or longer, the code will break.

Here, we've extracted the values from the Score column, scaled them and applied the size back to the scatter plot:

scaled marker size scatter plot matplotlib

Set Global Marker Size in Matplotlib Scatter Plot

If you'd like to detach the marker size from some variable, and would just like to set a standard, global size of markers in the scatter plot, you can simply pass in a single value for s:

import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('worldHappiness2019.csv')

fig, ax = plt.subplots(figsize=(10, 6))
ax.scatter(x = df['GDP per capita'], y = df['Generosity'], s = 100)
plt.xlabel("GDP per Capita")
plt.ylabel("Generosity Score")

plt.show()

This now results in:

global marker size matplotlib scatter plot

Conclusion

In this tutorial, we've gone over how to change the marker size in a Matplotlib Scatter Plot.

If you're interested in Data Visualization and don't know where to start, make sure to check out our book on Data Visualization in Python.

Data Visualization in Python, a book for beginner to intermediate Python developers, will guide you through simple data manipulation with Pandas, cover core plotting libraries like Matplotlib and Seaborn, and show you how to take advantage of declarative and experimental libraries like Altair.

Data Visualization in Python

Understand your data better with visualizations! With over 275+ pages, you'll learn the ins and outs of visualizing data in Python with popular libraries like Matplotlib, Seaborn, Bokeh, and more.

November 25, 2020 02:30 PM UTC


Real Python

PyQt Layouts: Create Professional-Looking GUI Applications

PyQt’s layout managers provide a user-friendly and productive way of arranging graphical components, or widgets, on a GUI. Laying out widgets properly will make your GUI applications look polished and professional. Learning to do so efficiently and effectively is a fundamental skill for you to get up and running with GUI application development using Python and PyQt.

In this tutorial, you’ll learn:

  • What the benefits are of using PyQt’s layout managers
  • How to programmatically lay out widgets on a GUI using PyQt’s layout managers
  • How to select the right layout manager for your GUI application
  • How to lay out widgets in main window–based and dialog-based applications

With this knowledge and skillset, you’ll be able to use Python and PyQt to create professional-looking GUI applications.

For a better understanding of how to use layout managers, some previous knowledge of how to create PyQt GUI applications and how to work with PyQt widgets would be helpful.

Free Bonus: 5 Thoughts On Python Mastery, a free course for Python developers that shows you the roadmap and the mindset you’ll need to take your Python skills to the next level.

Laying Out Graphical Elements on a GUI

When you’re creating graphical user interface (GUI) applications, a common issue is how to get your graphical components—buttons, menus, toolbars, labels, and so on—laid out coherently on your forms and windows. This process is known as GUI layout, and it’s an important step in creating GUI applications.

In the past, if you wanted to lay out graphical components, or widgets, on a window, then you would follow one of the following approaches:

  1. Decide on and manually set a static size and position for each widget on the window.
  2. Calculate and set the size and position of each widget dynamically.

The first approach is fairly direct, but it has at least the following drawbacks:

  • Your windows will be non-resizable, which might cause problems when displaying them on different screen resolutions.
  • Your labels might not support localization properly because the length of a given text changes between languages.
  • Your widgets will display differently on different platforms, which makes it difficult to write multiplatform applications that look good.

The second approach is more flexible. However, it also has drawbacks:

  • You have to do a lot of manual calculations to determine the right size and position of each widget.
  • You have to do some extra calculations to respond correctly to window resizing.
  • You have to redo all the calculations any time you modify the layout of your window.

Even though you can still use either of these two approaches to lay out your GUIs, most of the time you’ll want to use a third and more convenient approach implemented by most modern GUI frameworks or toolkits: layout managers.

Note: In some GUI frameworks, such as Tkinter, layout managers are also referred to as geometry managers.

Layout managers automatically arrange widgets on a GUI according to your specific needs. They avoid the compatibility drawbacks of the first approach as well as the annoying and complicated calculations of the second approach.

In the following sections, you’ll learn about PyQt’s built-in layout managers and how to use them to effectively lay out the graphical components of your GUI applications.

In PyQt, widgets are graphical components that you use as building blocks for your GUI applications. When you place a bunch of widgets on a window to create a GUI, you need to give them some order. You need to set the widgets’ size and position on the window, and you also need to define their behavior for when the user resizes the underlying window.

Note: Unfortunately, PyQt5’s official documentation has some incomplete sections. To work around this, you can check out the PyQt4 documentation, the Qt for Python documentation, or the original Qt documentation.

In this tutorial, you’ll find that most links will take you to the original Qt documentation, which is a better source of information in most cases.

To arrange the widgets on windows or forms in PyQt, you can use the following techniques:

  • Use .resize() and .move() on your widgets to provide an absolute size and position.
  • Reimplement .resizeEvent() and calculate your widgets’ size and position dynamically.
  • Use layout managers and let them do all the calculations and hard work for you.

These techniques generally correspond to the three different approaches for laying out a GUI that you saw in the previous section.

Again, calculating the size and position dynamically might be a good approach, but most of the time you’ll be better off using layout managers. In PyQt, layout managers are classes that provide the required functionality to automatically manage the size, position, and resizing behavior of the widgets in the layout.

Read the full article at https://realpython.com/python-pyqt-layout/ »


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

November 25, 2020 02:00 PM UTC


Codementor

How to write concurrent code using Python's Future

Using concurrency to speed up things is quite simple in Python using the concurrent.futures module. However, it's no silver bullet and one must know when to use it.

November 25, 2020 11:52 AM UTC

Comparison of new Python web frameworks

Python has become a popular option for building web services. Here's a list of 11 new web frameworks in Python that you should consider for your next project.

November 25, 2020 10:26 AM UTC