<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mouse Vs Python</title>
	<atom:link href="https://blog.pythonlibrary.org/feed/" rel="self" type="application/rss+xml" />
	<link>https://papayawhip-oyster-325761.hostingersite.com/</link>
	<description>Where You Can Learn All About Python Programming</description>
	<lastBuildDate>Thu, 02 Apr 2026 12:29:39 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://blog.pythonlibrary.org/wp-content/uploads/2019/05/cropped-narnyish_highres-32x32.png</url>
	<title>Mouse Vs Python</title>
	<link>https://papayawhip-oyster-325761.hostingersite.com/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Python Pop Quiz &#8211; Number Explosion</title>
		<link>https://blog.pythonlibrary.org/2026/04/02/python-pop-quiz-number-explosion/</link>
		
		<dc:creator><![CDATA[Mike]]></dc:creator>
		<pubDate>Thu, 02 Apr 2026 12:29:39 +0000</pubDate>
				<category><![CDATA[beginner]]></category>
		<category><![CDATA[Books]]></category>
		<category><![CDATA[Education]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[quiz]]></category>
		<guid isPermaLink="false">https://blog.pythonlibrary.org/?p=12775</guid>

					<description><![CDATA[<p>You will sometimes come across examples of code that use one or two asterisks. Depending on how the asterisks are used, they can mean different things to Python. Check your understanding of what a single asterisk means in the following quiz! The Quiz What will be the output if you run this code? numbers = [&#8230;]</p>
<p>The post <a href="https://blog.pythonlibrary.org/2026/04/02/python-pop-quiz-number-explosion/">Python Pop Quiz &#8211; Number Explosion</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p dir="auto">You will sometimes come across examples of code that use one or two asterisks. Depending on how the asterisks are used, they can mean different things to Python.</p>
<p dir="auto">Check your understanding of what a single asterisk means in the following quiz!</p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">The Quiz</h2>
<p><a id="user-content-the-quiz" class="anchor" href="https://github.com/driscollis/pyquiz_book/blob/main/02_number_explosion.md#the-quiz" aria-label="Permalink: The Quiz"></a></div>
<p dir="auto">What will be the output if you run this code?</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">numbers = range(3)
output = {*numbers}
print(output)</pre>
<p dir="auto">A) <code>{range}</code></p>
<p dir="auto">B) <code>(range)</code></p>
<p dir="auto">C) <code>[0, 1, 2]</code></p>
<p dir="auto">D) <code>(0, 1, 2)</code></p>
<p dir="auto">E) <code>{0, 1, 2}</code></p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">Hint</h2>
<p><a id="user-content-hint" class="anchor" href="https://github.com/driscollis/pyquiz_book/blob/main/02_number_explosion.md#hint" aria-label="Permalink: Hint"></a></div>
<p dir="auto">&#8220;Unpacking generalizations&#8221; is the term to look up if you get stuck..</p>
<p dir="auto"><img fetchpriority="high" decoding="async" class="aligncenter size-large wp-image-11679" src="https://blog.pythonlibrary.org/wp-content/uploads/2022/10/quiz_kick-1024x698.jpg" alt="The Python Quiz Book" width="1024" height="698" srcset="https://blog.pythonlibrary.org/wp-content/uploads/2022/10/quiz_kick-1024x698.jpg 1024w, https://blog.pythonlibrary.org/wp-content/uploads/2022/10/quiz_kick-300x204.jpg 300w, https://blog.pythonlibrary.org/wp-content/uploads/2022/10/quiz_kick-768x523.jpg 768w, https://blog.pythonlibrary.org/wp-content/uploads/2022/10/quiz_kick-1536x1046.jpg 1536w, https://blog.pythonlibrary.org/wp-content/uploads/2022/10/quiz_kick-2048x1395.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">The Answer</h2>
<p><a id="user-content-the-answer" class="anchor" href="https://github.com/driscollis/pyquiz_book/blob/main/02_number_explosion_answer.md#the-answer" aria-label="Permalink: The Answer"></a></div>
<p dir="auto"><strong>E) <code>{0, 1, 2}</code></strong></p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">Explanation</h2>
<p><a id="user-content-explanation" class="anchor" href="https://github.com/driscollis/pyquiz_book/blob/main/02_number_explosion_answer.md#explanation" aria-label="Permalink: Explanation"></a></div>
<p dir="auto">A single asterisk before a Python dictionary or list is known as the unpacking operator. In this example, you tell Python to unpack three integers (0 &#8211; 2) into a set.</p>
<p dir="auto">Here is the example running in a REPL:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">&gt;&gt;&gt; numbers = range(3)
&gt;&gt;&gt; output = {*numbers}
&gt;&gt;&gt; print(output)
{0, 1, 2}
&gt;&gt;&gt; print(type(output))
&lt;class 'set'&gt;</pre>
<p dir="auto">The code output shows that you have created a set!</p>
<p dir="auto">You can also use a single asterisk to unpack a dictionary&#8217;s keys:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">&gt;&gt;&gt; my_dict = {1: "one", 2: "two", 3: "three"}
&gt;&gt;&gt; print({*my_dict})
{1, 2, 3}</pre>
<p>If you want to take your knowledge of unpacking further, it can help to see Python functions use asterisks:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">&gt;&gt;&gt; def my_func(*args):
...     print(args)
... 
&gt;&gt;&gt; my_func(1)
(1,)
&gt;&gt;&gt; numbers = range(3)
&gt;&gt;&gt; output = {*numbers}
&gt;&gt;&gt; my_func(output)
({0, 1, 2},)
&gt;&gt;&gt; my_func(*output)
(0, 1, 2)</pre>
<p dir="auto">When you see a single asterisk in a function definition, the asterisk means that the function can take an unlimited number of arguments. In the second example, you pass in the set as a single argument, while in the last example, you use a single asterisk to unpack the numbers and pass them in as three separate arguments.</p>
<p dir="auto">For more information, see <a href="https://peps.python.org/pep-0448/" rel="nofollow">PEP 448 – Additional Unpacking Generalizations</a>, which has many more examples!</p>
<h2 dir="auto">Get the Book</h2>
<p>Want to try out over one HUNDRED more quizzes? Check out the book!</p>
<p><strong>Purchase at <a href="https://driscollis.gumroad.com/l/pyquiz">Gumroad</a> or <a href="https://leanpub.com/pyquiz">Leanpub</a> or <a href="https://www.amazon.com/dp/B0BVT8DZV1">Amazon</a></strong></p>
<p>The post <a href="https://blog.pythonlibrary.org/2026/04/02/python-pop-quiz-number-explosion/">Python Pop Quiz &#8211; Number Explosion</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Vibe Coding Pong with Python and pygame</title>
		<link>https://blog.pythonlibrary.org/2026/03/30/vibe-coding-pong-with-python-and-pygame/</link>
		
		<dc:creator><![CDATA[Mike]]></dc:creator>
		<pubDate>Mon, 30 Mar 2026 12:29:01 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Game]]></category>
		<category><![CDATA[pygame]]></category>
		<guid isPermaLink="false">https://blog.pythonlibrary.org/?p=12768</guid>

					<description><![CDATA[<p>Pong is one of the first computer games ever created, way back in 1972. If you have never heard of Pong, you can think of it as a kind of &#8220;tennis&#8221; game. There are two paddles, on each side of the screen. They move up and down. The goal is to bounce a ball between [&#8230;]</p>
<p>The post <a href="https://blog.pythonlibrary.org/2026/03/30/vibe-coding-pong-with-python-and-pygame/">Vibe Coding Pong with Python and pygame</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p dir="auto">Pong is one of the first computer games ever created, way back in 1972. If you have never heard of Pong, you can think of it as a kind of &#8220;tennis&#8221; game. There are two paddles, on each side of the screen. They move up and down. The goal is to bounce a ball between the two paddles. If you miss the ball, your opponent scores a point.</p>
<p dir="auto">Atari created Pong and put it in arcades. The name of the game is derived from the game of ping-pong. Pong has been remade many times, with different features and gameplay elements added or removed.</p>
<h3 class="header-anchor-post"><a href="https://driscollis.gumroad.com/l/vibegames" rel="">Want to know more? Get the Book!</a></h3>
<p dir="auto">You will use Anthropic&#8217;s Claude AI to create this game in Python using the pygame package.</p>
<p dir="auto">Let&#8217;s get started!</p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">Creating the Game</h2>
</div>
<blockquote>
<p dir="auto"><strong>Prompt</strong>: Please create the pong videogame using Python and pygame. Give the user a way to start a new game and keep score.</p>
</blockquote>
<p dir="auto">I&#8217;ll create a classic Pong game for you using Python and pygame. This will include two paddles, a ball, scoring, and the ability to start new games.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pygame
import sys
import random

# Initialize Pygame
pygame.init()

# Constants
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
PADDLE_WIDTH = 15
PADDLE_HEIGHT = 90
BALL_SIZE = 15
PADDLE_SPEED = 7
BALL_SPEED_X = 6
BALL_SPEED_Y = 6

# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (128, 128, 128)

class Paddle:
    def __init__(self, x, y):
        self.rect = pygame.Rect(
            x, y, PADDLE_WIDTH, PADDLE_HEIGHT)
        self.speed = PADDLE_SPEED
    
    def move_up(self):
        if self.rect.top &gt; 0:
            self.rect.y -= self.speed
    
    def move_down(self):
        if self.rect.bottom &lt; SCREEN_HEIGHT:
            self.rect.y += self.speed
    
    def draw(self, screen):
        pygame.draw.rect(screen, WHITE, self.rect)

class Ball:
    def __init__(self):
        self.rect = pygame.Rect(
            SCREEN_WIDTH // 2, 
            SCREEN_HEIGHT // 2, 
            BALL_SIZE,
            BALL_SIZE)
        self.reset_ball()
    
    def reset_ball(self):
        self.rect.center = (SCREEN_WIDTH // 2, 
            SCREEN_HEIGHT // 2)
        self.speed_x = BALL_SPEED_X * random.choice([-1, 1])
        self.speed_y = BALL_SPEED_Y * random.choice([-1, 1])
    
    def move(self):
        self.rect.x += self.speed_x
        self.rect.y += self.speed_y
        
        # Bounce off top and bottom walls
        if (self.rect.top &lt;= 0 
            or self.rect.bottom &gt;= SCREEN_HEIGHT):
            self.speed_y = -self.speed_y
    
    def draw(self, screen):
        pygame.draw.rect(screen, WHITE, self.rect)

class PongGame:
    def __init__(self):
        self.screen = pygame.display.set_mode(
            (SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption("Pong Game")
        self.clock = pygame.time.Clock()
        
        # Create game objects
        self.left_paddle = Paddle(
            30, SCREEN_HEIGHT // 2 - PADDLE_HEIGHT // 2)
        self.right_paddle = Paddle(
            SCREEN_WIDTH - 30 - PADDLE_WIDTH,
            SCREEN_HEIGHT // 2 - PADDLE_HEIGHT // 2)
        self.ball = Ball()
        
        # Scores
        self.left_score = 0
        self.right_score = 0
        self.font = pygame.font.Font(None, 74)
        self.small_font = pygame.font.Font(None, 36)
        
        # Game state
        self.game_state = "menu"  # "menu", "playing", "paused"
    
    def handle_collision(self):
        # Ball collision with paddles
        if self.ball.rect.colliderect(self.left_paddle.rect):
            # Only bounce if moving toward paddle
            if self.ball.speed_x &lt; 0:  
                self.ball.speed_x = -self.ball.speed_x
                # Add some variation based on where ball hits paddle
                hit_pos = (self.ball.rect.centery - self.left_paddle.rect.centery
                          ) / (PADDLE_HEIGHT / 2)
                self.ball.speed_y += hit_pos * 2
        
        if self.ball.rect.colliderect(self.right_paddle.rect):
            # Only bounce if moving toward paddle
            if self.ball.speed_x &gt; 0:  
                self.ball.speed_x = -self.ball.speed_x
                # Add some variation based on where ball hits paddle
                hit_pos = (self.ball.rect.centery - self.right_paddle.rect.centery
                          ) / (PADDLE_HEIGHT / 2)
                self.ball.speed_y += hit_pos * 2
        
        # Limit ball speed
        max_speed = 12
        if abs(self.ball.speed_y) &gt; max_speed:
            self.ball.speed_y = max_speed if self.ball.speed_y &gt; 0 else -max_speed
    
    def check_scoring(self):
        # Check if ball went off screen
        if self.ball.rect.left &lt;= 0:
            self.right_score += 1
            self.ball.reset_ball()
        elif self.ball.rect.right &gt;= SCREEN_WIDTH:
            self.left_score += 1
            self.ball.reset_ball()
    
    def handle_input(self):
        keys = pygame.key.get_pressed()
        
        if self.game_state == "playing":
            # Left paddle controls (W/S)
            if keys[pygame.K_w]:
                self.left_paddle.move_up()
            if keys[pygame.K_s]:
                self.left_paddle.move_down()
            
            # Right paddle controls (UP/DOWN arrows)
            if keys[pygame.K_UP]:
                self.right_paddle.move_up()
            if keys[pygame.K_DOWN]:
                self.right_paddle.move_down()
    
    def draw_menu(self):
        self.screen.fill(BLACK)
        
        title_text = self.font.render("PONG", True, WHITE)
        title_rect = title_text.get_rect(
            center=(SCREEN_WIDTH // 2, 150))
        self.screen.blit(title_text, title_rect)
        
        start_text = self.small_font.render(
            "Press SPACE to Start", True, WHITE)
        start_rect = start_text.get_rect(
            center=(SCREEN_WIDTH // 2, 250))
        self.screen.blit(start_text, start_rect)
        
        controls_text = [
            "Controls:",
            "Left Player: W (Up) / S (Down)",
            "Right Player: Arrow Keys",
            "Press R to restart during game",
            "Press ESC to return to menu"
        ]
        
        for i, text in enumerate(controls_text):
            rendered_text = self.small_font.render(
                text, True, GRAY if i == 0 else WHITE)
            text_rect = rendered_text.get_rect(
                center=(SCREEN_WIDTH // 2, 320 + i * 40))
            self.screen.blit(rendered_text, text_rect)
    
    def draw_game(self):
        self.screen.fill(BLACK)
        
        # Draw center line
        for i in range(0, SCREEN_HEIGHT, 20):
            if i % 40 == 0:
                pygame.draw.rect(
                    self.screen, 
                    WHITE, 
                    (SCREEN_WIDTH // 2 - 2, i, 4, 10))
        
        # Draw paddles and ball
        self.left_paddle.draw(self.screen)
        self.right_paddle.draw(self.screen)
        self.ball.draw(self.screen)
        
        # Draw scores
        left_score_text = self.font.render(
            str(self.left_score), True, WHITE)
        right_score_text = self.font.render(
            str(self.right_score), True, WHITE)
        
        self.screen.blit(left_score_text, (SCREEN_WIDTH // 4, 50))
        self.screen.blit(
            right_score_text, 
            (3 * SCREEN_WIDTH // 4 - right_score_text.get_width(),
             50))
        
        # Draw instructions
        instruction_text = self.small_font.render(
            "Press ESC for menu, R to restart", True, GRAY)
        instruction_rect = instruction_text.get_rect(
            center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT - 30))
        self.screen.blit(instruction_text, instruction_rect)
    
    def reset_game(self):
        self.left_score = 0
        self.right_score = 0
        self.ball.reset_ball()
        self.left_paddle.rect.y = (SCREEN_HEIGHT // 2 - 
            PADDLE_HEIGHT // 2)
        self.right_paddle.rect.y = (SCREEN_HEIGHT // 2 - 
            PADDLE_HEIGHT // 2)
    
    def run(self):
        running = True
        
        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                
                if event.type == pygame.KEYDOWN:
                    if (event.key == pygame.K_SPACE 
                        and self.game_state == "menu"):
                        self.game_state = "playing"
                        self.reset_game()
                    elif event.key == pygame.K_ESCAPE:
                        self.game_state = "menu"
                    elif (event.key == pygame.K_r 
                        and self.game_state == "playing"):
                        self.reset_game()
            
            if self.game_state == "menu":
                self.draw_menu()
            elif self.game_state == "playing":
                self.handle_input()
                self.ball.move()
                self.handle_collision()
                self.check_scoring()
                self.draw_game()
            
            pygame.display.flip()
            self.clock.tick(60)
        
        pygame.quit()
        sys.exit()

if __name__ == "__main__":
    game = PongGame()
    game.run()</pre>
<p dir="auto">I&#8217;ve created a complete Pong game in Python using pygame! Here are the key features:</p>
<p dir="auto"><strong>Game Features:</strong></p>
<ul dir="auto">
<li>Classic Pong gameplay with two paddles and a bouncing ball</li>
<li>Score tracking for both players</li>
<li>Menu system with game start option</li>
<li>Ability to restart games and return to menu</li>
</ul>
<p dir="auto"><strong>Controls:</strong></p>
<ul dir="auto">
<li>Left Player: W (up) / S (down)</li>
<li>Right Player: Arrow keys (up/down)</li>
<li>SPACE: Start new game from menu</li>
<li>R: Restart current game</li>
<li>ESC: Return to main menu</li>
</ul>
<p dir="auto"><strong>Game Mechanics:</strong></p>
<ul dir="auto">
<li>Ball bounces off top/bottom walls and paddles</li>
<li>Ball speed varies slightly based on where it hits the paddle</li>
<li>Scores increase when ball goes off either side</li>
<li>Ball resets to center after each score</li>
</ul>
<p dir="auto"><strong>To run the game:</strong></p>
<ul dir="auto">
<li>Make sure you have pygame installed: <code>pip install pygame</code></li>
<li>Save the code to a <code>.py</code> file (e.g., <code>pong.py</code>)</li>
<li>Run it with: <code>python pong.py</code></li>
</ul>
<p dir="auto">The game includes a clean menu system, smooth 60 FPS gameplay, and responsive controls. The ball physics include some randomization to keep gameplay interesting, and the paddle collisions add a bit of strategy by allowing players to influence the ball&#8217;s trajectory based on where they hit it.</p>
<blockquote>
<p dir="auto"><strong>Prompt</strong>: Can you explain how the code works?</p>
</blockquote>
<p dir="auto">I&#8217;ll break down how the Pong game code works, explaining each major component and how they work together.</p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">Code Structure Overview</h2>
<p>&nbsp;</p>
</div>
<p dir="auto">The code is organized using object-oriented programming with three main classes:</p>
<ul dir="auto">
<li><code>Paddle</code> &#8211; represents the player paddles</li>
<li><code>Ball</code> &#8211; handles the bouncing ball</li>
<li><code>PongGame</code> &#8211; manages the overall game logic and flow</li>
</ul>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element focus-visible" dir="auto" tabindex="-1" data-focus-visible-added="">1. Initialization and Constants</h2>
<pre class="EnlighterJSRAW" data-enlighter-language="python">pygame.init()
# Constants define game dimensions and speeds
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
PADDLE_SPEED = 7</pre>
<p dir="auto">The game starts by initializing pygame and defining constants for screen size, object dimensions, and movement speeds. Using constants makes the code easier to modify and maintain.</p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">2. The Paddle Class</h2>
<pre class="EnlighterJSRAW" data-enlighter-language="python">class Paddle:
    def __init__(self, x, y):
        self.rect = pygame.Rect(x, y, PADDLE_WIDTH, PADDLE_HEIGHT)</pre>
<p dir="auto">Each paddle is represented as a <code>pygame.Rect</code> object, which provides built-in collision detection and positioning. The paddle has methods to:</p>
<ul dir="auto">
<li><code>move_up()</code> and <code>move_down()</code> &#8211; handle movement with boundary checking</li>
<li><code>draw()</code> &#8211; renders the paddle as a white rectangle</li>
</ul>
<p dir="auto">The boundary checking ensures paddles can&#8217;t move off-screen:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">if self.rect.top &gt; 0:  # Don't go above screen
if self.rect.bottom &lt; SCREEN_HEIGHT:  # Don't go below screen</pre>
<h2 class="heading-element" dir="auto" tabindex="-1">3. The Ball Class</h2>
<pre class="EnlighterJSRAW" data-enlighter-language="python">class Ball:
    def reset_ball(self):
        self.speed_x = BALL_SPEED_X * random.choice([-1, 1])
        self.speed_y = BALL_SPEED_Y * random.choice([-1, 1])</pre>
<p dir="auto">The ball maintains its position and velocity. Key features:</p>
<ul dir="auto">
<li><code>reset_ball()</code> &#8211; centers the ball and gives it a random direction</li>
<li><code>move()</code> &#8211; updates position and handles wall bouncing</li>
<li>Wall collision detection flips the Y velocity: <code>self.speed_y = -self.speed_y</code></li>
</ul>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">4. Main Game Class Structure</h2>
<p>&nbsp;</p>
</div>
<p dir="auto">The PongGame class manages everything:</p>
<p dir="auto"><strong>Game States</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">self.game_state = "menu"  # "menu", "playing", "paused"</pre>
<p dir="auto">The game uses states to control what&#8217;s displayed and what input is accepted.</p>
<p dir="auto"><strong>Game Loop</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">def run(self):
    while running:
        # Handle events (keyboard, quit)
        # Update game logic based on current state
        # Draw everything
        # Control frame rate (60 FPS)</pre>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">5. Collision Detection</h2>
<p>&nbsp;</p>
</div>
<p dir="auto">The most complex part handles ball-paddle collisions:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">def handle_collision(self):
    if self.ball.rect.colliderect(self.left_paddle.rect):
        # Only bounce if moving toward paddle
        if self.ball.speed_x &lt; 0:  
            self.ball.speed_x = -self.ball.speed_x</pre>
<p dir="auto"><strong>Key points:</strong></p>
<ul dir="auto">
<li>Uses pygame&#8217;s built-in <code>colliderect()</code> for collision detection</li>
<li>Checks ball direction to prevent multiple bounces</li>
<li>Adds spin based on where the ball hits the paddle:</li>
</ul>
<pre class="EnlighterJSRAW" data-enlighter-language="python">hit_pos = (self.ball.rect.centery - 
           self.left_paddle.rect.centery
           ) / (PADDLE_HEIGHT / 2)
self.ball.speed_y += hit_pos * 2</pre>
<h2 class="heading-element focus-visible" dir="auto" tabindex="-1" data-focus-visible-added="">6. Input Handling</h2>
<pre class="EnlighterJSRAW" data-enlighter-language="python">def handle_input(self):
    keys = pygame.key.get_pressed()
    if keys[pygame.K_w]:
        self.left_paddle.move_up()</pre>
<p dir="auto">The game checks which keys are currently pressed each frame, allowing for smooth continuous movement. Different keys are handled based on the game state.</p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">7. Scoring System</h2>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">def check_scoring(self):
    if self.ball.rect.left &lt;= 0:  # Ball went off left side
        self.right_score += 1
        self.ball.reset_ball()</pre>
<p dir="auto">Scoring is checked every frame by seeing if the ball has moved past the screen edges.</p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">8. Rendering System</h2>
</div>
<p dir="auto">The game uses different drawing functions for different states:</p>
<ul dir="auto">
<li><code>draw_menu()</code> &#8211; shows title and instructions</li>
<li><code>draw_game()</code> &#8211; renders paddles, ball, scores, and game elements</li>
</ul>
<p dir="auto">The center dashed line is drawn using a loop:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">for i in range(0, SCREEN_HEIGHT, 20):
    if i % 40 == 0:  # Only draw every other dash
        pygame.draw.rect(
            self.screen, 
            WHITE, 
            (SCREEN_WIDTH // 2 - 2, i, 4, 10))</pre>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">9. Game Flow</h2>
</div>
<ol dir="auto">
<li><strong>Initialization</strong>: Create paddles, ball, set up pygame</li>
<li><strong>Main Loop:</strong></li>
</ol>
<ul dir="auto">
<li>Process input events</li>
<li>Update game logic (if playing)</li>
<li>Draw current state</li>
<li>Maintain 60 FPS with clock.tick(60)</li>
</ul>
<ol dir="auto" start="3">
<li>State Management: Switch between menu and gameplay based on user input</li>
</ol>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">Key Programming Concepts Used</h2>
</div>
<ul dir="auto">
<li><strong>Object-Oriented Design</strong>: Separate classes for different game elements</li>
<li><strong>Event-Driven Programming</strong>: Responding to keyboard and quit events</li>
<li><strong>Game Loop Pattern</strong>: Continuous update-draw cycle</li>
<li><strong>State Management</strong>: Different behaviors based on current game state</li>
<li><strong>Collision Detection</strong>: Using pygame&#8217;s rectangle collision methods</li>
<li><strong>Vector Math</strong>: Ball movement with X/Y velocity components</li>
</ul>
<p dir="auto">The code is structured to be easily extensible &#8211; you could add features like AI opponents, power-ups, or different game modes by building on this foundation.</p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">Running Pong</h2>
</div>
<p dir="auto">Now that you have the code and understand how to use it, you are ready to run the code. You can run your code in your Python IDE or on the command line like this:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">python pong.py</pre>
<p>When you first launch your game, you will see the following welcome screen:</p>
</div>
<p><img decoding="async" class="aligncenter size-large wp-image-12769" src="https://blog.pythonlibrary.org/wp-content/uploads/2026/03/pong_main-1024x805.png" alt="Pong main screen" width="1024" height="805" srcset="https://blog.pythonlibrary.org/wp-content/uploads/2026/03/pong_main-1024x805.png 1024w, https://blog.pythonlibrary.org/wp-content/uploads/2026/03/pong_main-300x236.png 300w, https://blog.pythonlibrary.org/wp-content/uploads/2026/03/pong_main-768x604.png 768w, https://blog.pythonlibrary.org/wp-content/uploads/2026/03/pong_main-1536x1207.png 1536w, https://blog.pythonlibrary.org/wp-content/uploads/2026/03/pong_main.png 1608w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<p>If you press the SPACE key, you will see the actual game, which will look something like this:</p>
<p><img decoding="async" class="aligncenter size-large wp-image-12772" src="https://blog.pythonlibrary.org/wp-content/uploads/2026/03/pong-1024x805.png" alt="Pong game play" width="1024" height="805" srcset="https://blog.pythonlibrary.org/wp-content/uploads/2026/03/pong-1024x805.png 1024w, https://blog.pythonlibrary.org/wp-content/uploads/2026/03/pong-300x236.png 300w, https://blog.pythonlibrary.org/wp-content/uploads/2026/03/pong-768x604.png 768w, https://blog.pythonlibrary.org/wp-content/uploads/2026/03/pong-1536x1207.png 1536w, https://blog.pythonlibrary.org/wp-content/uploads/2026/03/pong.png 1608w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<p dir="auto">Grab a friend or play against yourself. The game works pretty well, although playing solo can be rather challenging.</p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">Wrapping Up</h2>
<p><a id="user-content-wrapping-up" class="anchor" href="https://github.com/driscollis/creating_games_ai_book/blob/main/manuscript/02_pong.md#wrapping-up" aria-label="Permalink: Wrapping Up"></a></div>
<p dir="auto">Pong is a fun little game. Much like ping-pong or table tennis, the game is designed to be played with someone else. Technically, you could also create a computer opponent, but you usually play Pong between two people instead.</p>
<p dir="auto">You should play the game with a friend or family member. You can also study the code to discover how it works. Then, when you are ready, you can start improving the game.</p>
<h2 class="header-anchor-post">Get the Book</h2>
<div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent">
<div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA">
<div id="§get-the-book" class="pencraft pc-reset header-anchor offset-top"></div>
</div>
</div>
<p>This article is from my latest Python book, Vibe Coding Video Games with Python.</p>
<p>You can get <strong>Vibe Coding Video Games with Python</strong> at the following websites:</p>
<ul>
<li><a href="https://leanpub.com/vibegames" rel="">Leanpub</a></li>
<li><a href="https://driscollis.gumroad.com/l/vibegames" rel="">Gumroad</a></li>
<li><a href="https://amzn.to/4byWKaf" rel="">Amazon Kindle</a></li>
</ul>
</div>
</div>
<p>The post <a href="https://blog.pythonlibrary.org/2026/03/30/vibe-coding-pong-with-python-and-pygame/">Vibe Coding Pong with Python and pygame</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>The Python Show &#8211; Python Illustrated</title>
		<link>https://blog.pythonlibrary.org/2026/03/24/the-python-show-python-illustrated/</link>
		
		<dc:creator><![CDATA[Mike]]></dc:creator>
		<pubDate>Tue, 24 Mar 2026 17:59:43 +0000</pubDate>
				<category><![CDATA[beginner]]></category>
		<category><![CDATA[Books]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Podcast]]></category>
		<guid isPermaLink="false">https://blog.pythonlibrary.org/?p=12764</guid>

					<description><![CDATA[<p>In this episode, we hear from two sisters who put together a beginner&#8217;s book about Python. The unique hook for their book is that one sister wrote the text while the other did the illustrations. Listen in as we learn about these incredible sisters and how they got into software programming, writing, and technical education. [&#8230;]</p>
<p>The post <a href="https://blog.pythonlibrary.org/2026/03/24/the-python-show-python-illustrated/">The Python Show &#8211; Python Illustrated</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>In this episode, we hear from two sisters who put together a beginner&#8217;s book about Python. The unique hook for their book is that one sister wrote the text while the other did the illustrations. Listen in as we learn about these incredible sisters and how they got into software programming, writing, and technical education.</p>
<p><iframe style="width: 100%; max-width: 660px; overflow: hidden; border-radius: 10px;" src="https://embed.podcasts.apple.com/us/podcast/56-python-illustrated/id1691189730?i=1000755016348" height="175" frameborder="0" sandbox="allow-forms allow-popups allow-same-origin allow-scripts allow-storage-access-by-user-activation allow-top-navigation-by-user-activation"></iframe></p>
<p>You can check out their book, Python Illustrated, on <a href="https://www.packtpub.com/en-at/product/python-illustrated-9781836646327" rel="">Packt</a> or <a href="https://amzn.to/4do0JXY" rel="">Amazon</a>.</p>
<p>Maaike is an <a href="https://www.udemy.com/user/maaikevanputtencapgeminicom/" rel="">Udemy instructor</a>, and she also has courses on <a href="https://www.pluralsight.com/authors/maaike-vanputten" rel="">Pluralsight</a>.</p>
<p>This episode was originally published on <a href="https://www.pythonshow.com/">The Python Show</a>!</p>
<p>The post <a href="https://blog.pythonlibrary.org/2026/03/24/the-python-show-python-illustrated/">The Python Show &#8211; Python Illustrated</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Textual &#8211; Creating a Custom Checkbox</title>
		<link>https://blog.pythonlibrary.org/2026/03/16/textual-creating-a-custom-checkbox/</link>
		
		<dc:creator><![CDATA[Mike]]></dc:creator>
		<pubDate>Mon, 16 Mar 2026 19:42:08 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Textual]]></category>
		<category><![CDATA[TUI]]></category>
		<guid isPermaLink="false">https://blog.pythonlibrary.org/?p=12754</guid>

					<description><![CDATA[<p>Textual is a great Python user interface package. Textual lets you create a GUI-like interface in your terminal. You can use many different widgets in Textual. However, the widget you will be focusing on in this tutorial is the humble checkbox. Checkboxes are used for Boolean choices. They return a True if checked and a [&#8230;]</p>
<p>The post <a href="https://blog.pythonlibrary.org/2026/03/16/textual-creating-a-custom-checkbox/">Textual &#8211; Creating a Custom Checkbox</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Textual is a great Python user interface package. Textual lets you create a GUI-like interface in your terminal.</p>
<p>You can use many different widgets in Textual. However, the widget you will be focusing on in this tutorial is the humble checkbox.</p>
<p>Checkboxes are used for Boolean choices. They return a True if checked and a False if unchecked. You can use a checkbox as a clear visual cue to indicate whether one or more options are enabled or disabled.</p>
<p>In this tutorial, you will learn the following:</p>
<ul>
<li>How to create a standard checkbox</li>
<li>How to customize the checkbox widget</li>
</ul>
<p>Let’s get started!</p>
<h2 class="header-anchor-post">How to Create a Standard Checkbox</h2>
<p>You should always start with the default widget to see if it works for you. With that in mind, open up your favorite Python IDE and create a new file with the following code in it:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">from textual.app import App, ComposeResult
from textual.containers import VerticalScroll
from textual.widgets import Checkbox


class CheckboxApp(App[None]):

    def compose(self) -&gt; ComposeResult:
        with VerticalScroll():
            yield Checkbox("Mike")

    def on_checkbox_changed(self, event: Checkbox.Changed) -&gt; None:
        self.notify(f"Checkbox value: {event.value}")


if __name__ == "__main__":
    CheckboxApp().run()</pre>
<p>The example above is based on a code example from the <a href="https://textual.textualize.io/widgets/checkbox/#checkbox" rel="">Textual documentation</a>. You don’t have to use a <strong>VerticalScroll</strong> container here, but it is convenient when adding a series of widgets to the container.</p>
<p>Your main focus should be on the <strong>Checkbox</strong> itself. Here, you simply yield it from <strong>compose()</strong>, and then you catch the <strong>Checkbox.Changed</strong> event. When the event is fired, you display a notification to the user indicating that they have changed the checkbox value.</p>
<p>When you run this code, you will see something like this:</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-12758 size-full" src="https://blog.pythonlibrary.org/wp-content/uploads/2026/03/normal_check_output.png" alt="Textual checkbox" width="854" height="335" srcset="https://blog.pythonlibrary.org/wp-content/uploads/2026/03/normal_check_output.png 854w, https://blog.pythonlibrary.org/wp-content/uploads/2026/03/normal_check_output-300x118.png 300w, https://blog.pythonlibrary.org/wp-content/uploads/2026/03/normal_check_output-768x301.png 768w" sizes="auto, (max-width: 854px) 100vw, 854px" /></p>
<p>However, if you want to make the widget’s borders always visible, then you’ll need to add a border to the widget.</p>
<p>But what if you want the checkbox to be completely empty, too, rather than a greyed-out “X”? That is what you will learn how to do in the next section!</p>
<h2 data-pm-slice="1 1 []">How to Customize the Checkbox Widget</h2>
<p>Having a greyed out “X” isn’t necessarily bad thing if you have set up your Textual application to have a lighter background. But if you are using a default or dark background, then you will have some contrast issues.</p>
<p>Many GUI toolkits will show a checkbox as empty for its False state, though, while Textual defaults to a greyed-out “X.” If you want to change the character that is shown or make it an empty box like other toolkits, then you will need to learn how to customize the widget itself.</p>
<p>Fortunately, making a custom widget in Textual is very straightforward. Create a new Python file in your IDE and enter the following code:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">from textual.app import App, ComposeResult
from textual.containers import VerticalScroll
from textual.widgets import Checkbox

class CustomCheck(Checkbox):
    BUTTON_INNER = " "

    def toggle(self) -&gt; None:
        if self.value:
            CustomCheck.BUTTON_INNER = " "
        else:
            CustomCheck.BUTTON_INNER = "X"
        self.value = not self.value
        return self


class CheckboxApp(App[None]):
    #CSS_PATH = "checkbox.tcss"

    def compose(self) -&gt; ComposeResult:
        check = CustomCheck("Mike")

        with VerticalScroll():
            yield check

    def on_checkbox_changed(self, event: Checkbox.Changed) -&gt; None:
        self.notify(f"Checkbox value: {event.value}")


if __name__ == "__main__":
    CheckboxApp().run()</pre>
<p>When you want to customize a pre-existing widget in Textual, you will almost always subclass it. So here, you subclass the <strong>Checkbox</strong> class to create a new <strong>CustomCheck</strong> class. Next, you override the <strong>BUTTON_INNER </strong>class attribute as well as the <strong>toggle()</strong> method.</p>
<p>If you go looking at the source code, you will find that <strong>BUTTON_INNER </strong>defaults to the “X” so here you are defaulting it to an empty string. Then you update <strong>toggle()</strong> to swap the “X” in when it is checked, and swap it back out when it is unchecked.</p>
<p>The other change is to use the new widget class in your application code.</p>
<p>To increase the widget&#8217;s visibility, you can add a border using Textual CSS. Create a new file called <strong>checkbox.tcss</strong> and add the following code to it:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="css">CustomCheck {
    border: round green;
}</pre>
<p>Make sure you save this file in the same folder as your Python file.</p>
<p>Now, when you run this code, you will see the following:</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-12759 size-full" src="https://blog.pythonlibrary.org/wp-content/uploads/2026/03/custom_check_output2.png" alt="Custom Textual checkbox" width="852" height="320" srcset="https://blog.pythonlibrary.org/wp-content/uploads/2026/03/custom_check_output2.png 852w, https://blog.pythonlibrary.org/wp-content/uploads/2026/03/custom_check_output2-300x113.png 300w, https://blog.pythonlibrary.org/wp-content/uploads/2026/03/custom_check_output2-768x288.png 768w" sizes="auto, (max-width: 852px) 100vw, 852px" /></p>
<p>Good job! You now have a custom checkbox.</p>
<h2>Wrapping Up</h2>
<p>Textual is a great way for you to create beautiful user interfaces in your terminal. In this tutorial, you learned how to create a regular checkbox widget and then learned how to create a custom checkbox.</p>
<p>You can apply this knowledge to customize other widgets in Textual. You will need to study the widget’s code closely to understand how it works so you can modify it successfully. You may have to go through several iterations to get exactly what you want.</p>
<p>Don’t give up! You’ll get there eventually, and then you will be proud of yourself for sticking to it!</p>
<h2 class="header-anchor-post">Learn More</h2>
<p>If you thought this article was interesting you and you want to learn more about Textual, check out the following links:</p>
<ul>
<li>The Textual <a href="https://textual.textualize.io/" rel="">website</a></li>
<li><a href="https://driscollis.gumroad.com/l/textual" rel="">Creating TUI Applications with Textual and Python</a> (book)</li>
</ul>
<p>The post <a href="https://blog.pythonlibrary.org/2026/03/16/textual-creating-a-custom-checkbox/">Textual &#8211; Creating a Custom Checkbox</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Python Typing Book Kickstarter</title>
		<link>https://blog.pythonlibrary.org/2026/02/03/python-typing-book-kickstarter/</link>
		
		<dc:creator><![CDATA[Mike]]></dc:creator>
		<pubDate>Tue, 03 Feb 2026 18:17:00 +0000</pubDate>
				<category><![CDATA[beginner]]></category>
		<category><![CDATA[Books]]></category>
		<category><![CDATA[intermediate]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://blog.pythonlibrary.org/?p=12748</guid>

					<description><![CDATA[<p>Python has had type hinting support since Python 3.5, over TEN years ago! However, Python’s type annotations have changed repeatedly over the years. In Python Typing: Type Checking for Python Programmers, you will learn all you need to know to add type hints to your Python applications effectively. You will also learn how to use Python [&#8230;]</p>
<p>The post <a href="https://blog.pythonlibrary.org/2026/02/03/python-typing-book-kickstarter/">Python Typing Book Kickstarter</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Python has had type hinting support since Python 3.5, over TEN years ago! However, Python’s type annotations have changed repeatedly over the years. In <strong>Python Typing: Type Checking for Python Programmers</strong>, you will learn all you need to know to add type hints to your Python applications effectively.</p>
<p>You will also learn how to use Python type checkers, configure them, and set them up in pre-commit or GitHub Actions. This knowledge will give you the power to check your code and your team’s code automatically before merging, hopefully catching defects before they make it into your products.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium wp-image-12749" src="https://blog.pythonlibrary.org/wp-content/uploads/2026/02/python_typing_cover-200x300.webp" alt="Python Typing Book Cover" width="200" height="300" srcset="https://blog.pythonlibrary.org/wp-content/uploads/2026/02/python_typing_cover-200x300.webp 200w, https://blog.pythonlibrary.org/wp-content/uploads/2026/02/python_typing_cover-683x1024.webp 683w, https://blog.pythonlibrary.org/wp-content/uploads/2026/02/python_typing_cover-768x1152.webp 768w, https://blog.pythonlibrary.org/wp-content/uploads/2026/02/python_typing_cover-1024x1536.webp 1024w, https://blog.pythonlibrary.org/wp-content/uploads/2026/02/python_typing_cover-1365x2048.webp 1365w, https://blog.pythonlibrary.org/wp-content/uploads/2026/02/python_typing_cover-scaled.webp 1707w" sizes="auto, (max-width: 200px) 100vw, 200px" /></p>
<p class="button-wrapper" style="text-align: center;" data-attrs="{&quot;url&quot;:&quot;https://www.kickstarter.com/projects/driscollis/python-typing-book&quot;,&quot;text&quot;:&quot;Support the Book!&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.kickstarter.com/projects/driscollis/python-typing-book" rel="">Support the Book!</a></p>
<h3 class="header-anchor-post"><strong>What You’ll Learn</strong></h3>
<div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent">
<div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA">
<div id="§what-youll-learn" class="pencraft pc-reset header-anchor offset-top"></div>
</div>
</div>
<p>You will learn all about Python’s support for type hinting (annotations). Specifically, you will learn about the following topics:</p>
<ul>
<li>Variable annotations</li>
<li>Function annotations</li>
<li>Type aliases</li>
<li>New types</li>
<li>Generics</li>
<li>Hinting callables</li>
<li>Annotating TypedDict</li>
<li>Annotating Decorators and Generators</li>
<li>Using Mypy for type checking</li>
<li>Mypy configuration</li>
<li>Using ty for type checking</li>
<li>ty configuration</li>
<li>and more!</li>
</ul>
<h3 class="header-anchor-post"><strong>Rewards to Choose From</strong></h3>
<div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent">
<div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA">
<div id="§rewards-to-choose-from" class="pencraft pc-reset header-anchor offset-top"></div>
</div>
</div>
<p>There are several different rewards you can get in this Kickstarter:</p>
<ul>
<li>A signed paperback copy of the book (See Stretch Goals)</li>
<li>An eBook copy of the book in PDF and ePub</li>
<li>A t-shirt with the cover art from the book (See Stretch Goals)</li>
<li>Other Python eBooks</li>
</ul>
<p class="button-wrapper" style="text-align: center;" data-attrs="{&quot;url&quot;:&quot;https://www.kickstarter.com/projects/driscollis/python-typing-book&quot;,&quot;text&quot;:&quot;Kickstart the Book&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.kickstarter.com/projects/driscollis/python-typing-book" rel="">Kickstart the Book</a></p>
<p>The post <a href="https://blog.pythonlibrary.org/2026/02/03/python-typing-book-kickstarter/">Python Typing Book Kickstarter</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>New Book: Vibe Coding Video Games with Python</title>
		<link>https://blog.pythonlibrary.org/2026/01/19/new-book-vibe-coding-video-games-with-python/</link>
		
		<dc:creator><![CDATA[Mike]]></dc:creator>
		<pubDate>Mon, 19 Jan 2026 14:25:39 +0000</pubDate>
				<category><![CDATA[beginner]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Vibe Coding]]></category>
		<guid isPermaLink="false">https://blog.pythonlibrary.org/?p=12743</guid>

					<description><![CDATA[<p>My latest book, Vibe Coding Video Games with Python, is now available as an eBook. The paperback will be coming soon, hopefully by mid-February at the latest. The book is around 183 pages in length and is 6&#215;9” in size. In this book, you will learn how to use artificial intelligence to create mini-games. You will attempt [&#8230;]</p>
<p>The post <a href="https://blog.pythonlibrary.org/2026/01/19/new-book-vibe-coding-video-games-with-python/">New Book: Vibe Coding Video Games with Python</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>My latest book, <strong>Vibe Coding Video Games with Python,</strong> is now available as an eBook. The paperback will be coming soon, hopefully by mid-February at the latest. The book is around 183 pages in length and is 6&#215;9” in size.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium wp-image-12744" src="https://blog.pythonlibrary.org/wp-content/uploads/2026/01/Vibe_coding_video_games600-188x300.jpg" alt="Vibe Coding Video Games with Python" width="188" height="300" srcset="https://blog.pythonlibrary.org/wp-content/uploads/2026/01/Vibe_coding_video_games600-188x300.jpg 188w, https://blog.pythonlibrary.org/wp-content/uploads/2026/01/Vibe_coding_video_games600.jpg 376w" sizes="auto, (max-width: 188px) 100vw, 188px" /></p>
<p>In this book, you will learn how to use artificial intelligence to create mini-games. You will attempt to recreate the look and feel of various classic video games. The intention is not to violate copyright or anything of the sort, but instead to learn the limitations and the power of AI.</p>
<p>Instead, you will simply be learning about whether or not you can use AI to help you know how to create video games. Can you do it with no previous knowledge, as the AI proponents say? Is it really possible to create something just by writing out questions to the ether?</p>
<p>You will use various large language models (LLMs), such as Google Gemini, Grok, Mistral, and CoPilot, to create these games. You will discover the differences and similarities between these tools. You may be surprised to find that some tools give much more context than others.</p>
<p>AI is certainly not a cure-all and is far from perfect. You will quickly discover AI’s limitations and learn some strategies for solving those kinds of issues.</p>
<h3 class="header-anchor-post"><strong>What You’ll Learn</strong></h3>
<p>You’ll be creating “clones” of some popular games. However, these games will only be the first level and may or may not be fully functional.</p>
<ul>
<li>Chapter 1 – The Snake Game</li>
<li>Chapter 2 – Pong Clone</li>
<li>Chapter 3 – Frogger Clone</li>
<li>Chapter 4 – Space Invaders Clone</li>
<li>Chapter 5 – Minesweeper Clone</li>
<li>Chapter 6 – Luna Lander Clone</li>
<li>Chapter 7 – Asteroids Clone</li>
<li>Chapter 8 – Tic-Tac-Toe</li>
<li>Chapter 9 – Pole Position Clone</li>
<li>Chapter 10 – Connect Four</li>
<li>Chapter 11 – Adding Sprites</li>
</ul>
<h3 class="header-anchor-post">Where to Purchase</h3>
<div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent">
<div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA"><span style="font-size: 16px;">You can get </span><strong style="font-size: 16px;">Vibe Coding Video Games with Python</strong><span style="font-size: 16px;"> at the following websites:</span></div>
</div>
<ul>
<li><a href="https://leanpub.com/vibegames" rel="">Leanpub</a></li>
<li><a href="https://driscollis.gumroad.com/l/vibegames" rel="">Gumroad</a></li>
<li><a href="https://amzn.to/4byWKaf" rel="">Amazon Kindle</a></li>
</ul>
<p>The post <a href="https://blog.pythonlibrary.org/2026/01/19/new-book-vibe-coding-video-games-with-python/">New Book: Vibe Coding Video Games with Python</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to Type Hint a Decorator in Python</title>
		<link>https://blog.pythonlibrary.org/2026/01/14/how-to-type-hint-a-decorator-in-python/</link>
		
		<dc:creator><![CDATA[Mike]]></dc:creator>
		<pubDate>Wed, 14 Jan 2026 17:04:47 +0000</pubDate>
				<category><![CDATA[intermediate]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Typing]]></category>
		<guid isPermaLink="false">https://blog.pythonlibrary.org/?p=12734</guid>

					<description><![CDATA[<p>Decorators are a concept that can trip up new Python users. You may find this definition helpful: A decorator is a function that takes in another function and adds new functionality to it without modifying the original function. Functions can be used just like any other data type in Python. A function can be passed [&#8230;]</p>
<p>The post <a href="https://blog.pythonlibrary.org/2026/01/14/how-to-type-hint-a-decorator-in-python/">How to Type Hint a Decorator in Python</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Decorators are a concept that can trip up new Python users. You may find this definition helpful: A decorator is a function that takes in another function and adds new functionality to it without modifying the original function.</p>
<p>Functions can be used just like any other data type in Python. A function can be passed to a function or returned from a function, just like a string or integer.</p>
<p>If you have jumped on the type-hinting bandwagon, you will probably want to add type hints to your decorators. That has been difficult until fairly recently.</p>
<p>Let’s see how to type hint a decorator!</p>
<h2 class="header-anchor-post">Type Hinting a Decorator the Wrong Way</h2>
<div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent">
<div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA">
<p><span style="font-size: 16px;">You might think that you can use a </span><code style="font-size: 16px; font-style: inherit; font-weight: inherit;">TypeVar</code><span style="font-size: 16px;"> to type hint a decorator. You will try that first.</span></p>
</div>
</div>
<p>Here’s an example:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">from functools import wraps
from typing import Any, Callable, TypeVar


Generic_function = TypeVar("Generic_function", bound=Callable[..., Any])

def info(func: Generic_function) -&gt; Generic_function:
    @wraps(func)
    def wrapper(*args: Any, **kwargs: Any) -&gt; Any:
        print('Function name: ' + func.__name__)
        print('Function docstring: ' + str(func.__doc__))
        result = func(*args, **kwargs)
        return result
    return wrapper

@info
def doubler(number: int) -&gt; int:
    """Doubles the number passed to it"""
    return number * 2

print(doubler(4))</pre>
<p>If you run <code>mypy —strict info_decorator.py</code> you will get the following output:</p>
<div class="captioned-image-container">
<figure>
<div class="image2-inset can-restack"><picture><source srcset="https://substackcdn.com/image/fetch/$s_!fHQx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca544bc5-619b-460e-8078-50a6c26b0277_1968x554.png 424w, https://substackcdn.com/image/fetch/$s_!fHQx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca544bc5-619b-460e-8078-50a6c26b0277_1968x554.png 848w, https://substackcdn.com/image/fetch/$s_!fHQx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca544bc5-619b-460e-8078-50a6c26b0277_1968x554.png 1272w, https://substackcdn.com/image/fetch/$s_!fHQx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca544bc5-619b-460e-8078-50a6c26b0277_1968x554.png 1456w" type="image/webp" sizes="100vw" /></picture></div>
<div>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">info_decorator.py:14: error: Incompatible return value type (got "_Wrapped[[VarArg(Any), KwArg(Any)], Any, [VarArg(Any), KwArg(Any)], Any]", expected "Generic_function")  [return-value]
Found 1 error in 1 file (checked 1 source file)</pre>
<p>That’s a confusing error! Feel free to search for an answer.</p>
<p>The answers that you find will probably vary from just ignoring the function (i.e. not type hinting it at all) to using something called a <code>ParamSpec</code>.</p>
<p>Let’s try that next!</p>
<h2 class="header-anchor-post">Using a ParamSpec for Type Hinting</h2>
<div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent">
<div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA"><span style="font-size: 16px;">The </span><strong style="font-size: 16px;">ParamSpec</strong><span style="font-size: 16px;"> is a class in Python’s </span><code style="font-size: 16px; font-style: inherit; font-weight: inherit;">typing</code><span style="font-size: 16px;"><span style="font-size: 16px;"> module. Here’s what the docstring says about ParamSpec:</p>
<p></span></span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">class ParamSpec(object):
  """ Parameter specification variable.
  
  The preferred way to construct a parameter specification is via the
  dedicated syntax for generic functions, classes, and type aliases,
  where the use of '**' creates a parameter specification::
  
      type IntFunc[**P] = Callable[P, int]
  
  For compatibility with Python 3.11 and earlier, ParamSpec objects
  can also be created as follows::
  
      P = ParamSpec('P')
  
  Parameter specification variables exist primarily for the benefit of
  static type checkers.  They are used to forward the parameter types of
  one callable to another callable, a pattern commonly found in
  higher-order functions and decorators.  They are only valid when used
  in ``Concatenate``, or as the first argument to ``Callable``, or as
  parameters for user-defined Generics. See class Generic for more
  information on generic types.
  
  An example for annotating a decorator::
  
      def add_logging[**P, T](f: Callable[P, T]) -&gt; Callable[P, T]:
          '''A type-safe decorator to add logging to a function.'''
          def inner(*args: P.args, **kwargs: P.kwargs) -&gt; T:
              logging.info(f'{f.__name__} was called')
              return f(*args, **kwargs)
          return inner
  
      @add_logging
      def add_two(x: float, y: float) -&gt; float:
          '''Add two numbers together.'''
          return x + y
  
  Parameter specification variables can be introspected. e.g.::
  
      &gt;&gt;&gt; P = ParamSpec("P")
      &gt;&gt;&gt; P.__name__
      'P'
  
  Note that only parameter specification variables defined in the global
  scope can be pickled.
   """</pre>
<p>In short, you use a ParamSpec to construct a parameter specification for a generic function, class, or type alias.</p>
<p>To see what that means in code, you can update the previous decorator to look like this:<span style="font-size: 16px;"> </span></p>
</div>
<div>
<pre class="EnlighterJSRAW" data-enlighter-language="python">from functools import wraps
from typing import Callable, ParamSpec, TypeVar


P = ParamSpec("P")
R = TypeVar("R")

def info(func: Callable[P, R]) -&gt; Callable[P, R]:
    @wraps(func)
    def wrapper(*args: P.args, **kwargs: P.kwargs) -&gt; R:
        print('Function name: ' + func.__name__)
        print('Function docstring: ' + str(func.__doc__))
        return func(*args, **kwargs)
    return wrapper

@info
def doubler(number: int) -&gt; int:
    """Doubles the number passed to it"""
    return number * 2

print(doubler(4))</pre>
<p>Here, you create a ParamSpec and a TypeVar. You tell the decorator that it takes in a Callable with a generic set of parameters (P), and you use TypeVar (R) to specify a generic return type.</p>
<p>If you run mypy on this updated code, it will pass! Good job!</p>
<h2>What About PEP 695?</h2>
<p><a href="https://peps.python.org/pep-0695/" rel="">PEP 695</a> adds a new wrinkle to adding type hints to decorators by updating the parameter specification in Python in 3.12.</p>
<p>The main thrust of this PEP is to “simplify” the way you specify type parameters within a generic class, function, or type alias.</p>
<p>In a lot of ways, it does clean up the code as you no longer need to import ParamSpec of TypeVar when using this new syntax. Instead, it feels almost magical.</p>
<p>Here’s the updated code:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">from functools import wraps
from typing import Callable


def info[**P, R](func: Callable[P, R]) -&gt; Callable[P, R]:
    @wraps(func)
    def wrapper(*args: P.args, **kwargs: P.kwargs) -&gt; R:
        print('Function name: ' + func.__name__)
        print('Function docstring: ' + str(func.__doc__))
        return func(*args, **kwargs)
    return wrapper

@info
def doubler(number: int) -&gt; int:
    """Doubles the number passed to it"""
    return number * 2

print(doubler(4))</pre>
<p>Notice that at the beginning of the function you have square brackets. That is basically declaring your ParamSpec implicitly. The “R” is again the return type. The rest of the code is the same as before.</p>
<p>When you run mypy against this version of the type hinted decorator, you will see that it passes happily.</p>
<h2>Wrapping Up</h2>
<p>Type hinting can still be a hairy subject, but the newer the Python version that you use, the better the type hinting capabilities are.</p>
<p>Of course, since Python itself doesn’t enforce type hinting, you can just skip all this too. But if your employer like type hinting, hopefully this article will help you out.</p>
<h2>Related Reading</h2>
<ul>
<li>Learn all about decorators in <a href="https://blog.pythonlibrary.org/2017/07/18/python-all-about-decorators/">this sister article</a></li>
</ul>
</div>
</div>
</div>
</figure>
</div>
<p>The post <a href="https://blog.pythonlibrary.org/2026/01/14/how-to-type-hint-a-decorator-in-python/">How to Type Hint a Decorator in Python</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to Switch to ty from Mypy</title>
		<link>https://blog.pythonlibrary.org/2026/01/09/how-to-switch-to-ty-from-mypy/</link>
		
		<dc:creator><![CDATA[Mike]]></dc:creator>
		<pubDate>Fri, 09 Jan 2026 15:16:16 +0000</pubDate>
				<category><![CDATA[beginner]]></category>
		<category><![CDATA[intermediate]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Type Checking]]></category>
		<guid isPermaLink="false">https://blog.pythonlibrary.org/?p=12738</guid>

					<description><![CDATA[<p>Python has supported type hinting for quite a few versions now, starting way back in 3.5. However, Python itself does not enforce type checking. Instead, you need to use an external tool or IDE. The first and arguably most popular is mypy. Microsoft also has a Python type checker that you can use in VS Code [&#8230;]</p>
<p>The post <a href="https://blog.pythonlibrary.org/2026/01/09/how-to-switch-to-ty-from-mypy/">How to Switch to ty from Mypy</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Python has supported type hinting for quite a few versions now, starting way back in 3.5. However, Python itself does not enforce type checking. Instead, you need to use an external tool or IDE. The first and arguably most popular is <a href="https://mypy.readthedocs.io/en/stable/index.html" rel="">mypy</a>.</p>
<p>Microsoft also has a Python type checker that you can use in VS Code called <a href="https://github.com/microsoft/pyright" rel="">Pyright,</a> and then there’s the lesser-known <a href="https://pyrefly.org/" rel="">Pyrefly</a> type checker and language server.</p>
<p>The newest type checker on the block is <a href="https://astral.sh/blog/ty" rel="">Astral&#8217;s ty</a>, the maker of Ruff. Ty is another super-fast Python utility written in Rust.</p>
<p>In this article, you will learn how to switch your project to use ty locally and in GitHub Actions.</p>
<h2 class="header-anchor-post">Installation</h2>
<div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent">
<div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA">
<p><span style="font-size: 16px;">You can run ty with uvx if you do not want to install it by using the following command in your terminal: </span><strong style="font-size: 16px;">uvx ty</strong></p>
</div>
</div>
<p>To install ty with uv, run the following:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">uv tool install ty@latest</pre>
<p>If you do not want to use uv, you can use the standalone installer. Instructions vary depending on your platform, so it is best to refer to the <a href="https://docs.astral.sh/ty/installation/#installing-with-the-standalone-installer" rel="">documentation </a>for the latest information.</p>
<p>Note: Technically, you can use pip or pipx to install ty as well.</p>
<h2 class="header-anchor-post">Running ty Locally</h2>
<div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent">
<div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA"><span style="font-size: 16px;">Once you have ty installed, you can run it using any of the following:</span></div>
</div>
<h3 class="header-anchor-post">Running with uv</h3>
<div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent">
<div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA">
<pre class="EnlighterJSRAW" data-enlighter-language="generic">uv run ty</pre>
<p><span style="font-size: 1.5em; font-weight: bold;">Running without Installation</span></p>
</div>
</div>
<div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent">
<div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA">
<pre class="EnlighterJSRAW" data-enlighter-language="generic">uvx ty</pre>
<p><span style="font-size: 1.5em; font-weight: bold;">Running ty Directly</span></p>
</div>
</div>
<div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent">
<div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA">
<pre class="EnlighterJSRAW" data-enlighter-language="generic">ty check</pre>
<p><span style="font-size: 1.7em; font-weight: bold;">Configuring ty</span></p>
</div>
</div>
<div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent">
<div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA"><span style="font-size: 16px;">You can configure ty using either of the following:</span></div>
</div>
<ul>
<li>pyproject.toml</li>
<li>ty.toml</li>
</ul>
<p>There are many rules that you can change. Check out the <a href="https://docs.astral.sh/ty/rules/" rel="">documentation</a> for full details.</p>
<p>In general, if you run mypy in strict mode, then running ty without changing any of its settings is very similar. However, ty currently does not highlight missing type hints. If you need to enforce adding type hints, you can use <a href="https://docs.astral.sh/ruff/rules/#flake8-annotations-ann" rel="">Ruff’s flake8-annotations</a>.</p>
<p>Here is how to enable the flak8-annotations in your <strong>pyproject.toml</strong> file:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-12739" src="https://blog.pythonlibrary.org/wp-content/uploads/2026/01/ruff_flake8.png" alt="Using Flake8 annotations in Ruff" width="1226" height="428" srcset="https://blog.pythonlibrary.org/wp-content/uploads/2026/01/ruff_flake8.png 1226w, https://blog.pythonlibrary.org/wp-content/uploads/2026/01/ruff_flake8-300x105.png 300w, https://blog.pythonlibrary.org/wp-content/uploads/2026/01/ruff_flake8-1024x357.png 1024w, https://blog.pythonlibrary.org/wp-content/uploads/2026/01/ruff_flake8-768x268.png 768w" sizes="auto, (max-width: 1226px) 100vw, 1226px" /></p>
<p>If you have other rules already selected, you can add “ANN” to the end of the list to enable it.</p>
<h2 class="header-anchor-post">Running ty in GitHub Actions</h2>
<div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent">
<div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA"><span style="font-size: 16px;">Running ty in GitHub Actions is a great, free way to type-check your PRs. To add ty to GitHub Actions, create a new file named </span><strong style="font-size: 16px;">ty.yml</strong><span style="font-size: 16px;"> in your GitHub repo in the following location:</span></div>
</div>
<p><strong>.github/workflows/ty.yml</strong></p>
<p>Make sure you include the leading period!</p>
<p>Next, inside your yaml file, you will add the following code:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="yaml">name: ty
on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]
  workflow_dispatch:
jobs:
  build:
    if: github.event.pull_request.draft == false
    runs-on: self-hosted
    steps:
      - uses: actions/checkout@v3
      - name: Install Python
        uses: actions/setup-python@v4
        with:
          python-version: “3.12”
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install ty==0.0.7      
      - name: Run ty
        run: ty check
        continue-on-error: false</pre>
<p>Now, when your team opens a new PR in your project, it will automatically run ty against it. Feel free to update the Python version to the one you are using. Also note that this GitHub Action sets the ty version to 0.0.7, which you may need to update as newer releases become available.</p>
<h2 class="header-anchor-post">Using ty with pre-commit</h2>
<div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent">
<div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA"><span style="font-size: 16px;">The ty project does not have official support for </span><a style="font-size: 16px; background-color: #ffffff;" href="https://pre-commit.com/" rel="">pre-commit</a><span style="font-size: 16px;"> yet. However, there is a </span><a style="font-size: 16px; background-color: #ffffff;" href="https://github.com/astral-sh/ty/issues/269" rel="">ticket </a><span style="font-size: 16px;">to add this functionality. In the meantime, several other people have provided their own workarounds to allow you to use ty with pre-commit:</span></div>
</div>
<ul>
<li><a href="https://github.com/NSPC911/ty-pre-commit" rel="">https://github.com/NSPC911/ty-pre-commit</a></li>
<li><a href="https://github.com/JacobCoffee/ty-pre-commit" rel="">https://github.com/JacobCoffee/ty-pre-commit</a></li>
<li><a href="https://github.com/hoxbro/ty-pre-commit" rel="">https://github.com/hoxbro/ty-pre-commit</a></li>
<li><a href="https://github.com/allganize/ty-pre-commit" rel="">https://github.com/allganize/ty-pre-commit</a></li>
<li><a href="https://foundry.fsky.io/vel/ty-pre-commit" rel="">https://foundry.fsky.io/vel/ty-pre-commit</a></li>
</ul>
<p>When Astral supports pre-commit itself, you should update your pre-commit configuration accordingly.</p>
<p>However, for this tutorial, you can use that first link which tells you to add the following to your <code>.pre-commit-config.yaml</code>:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-12740" src="https://blog.pythonlibrary.org/wp-content/uploads/2026/01/ty-pre-commit.png" alt="Using ty in pre-commit" width="1226" height="640" srcset="https://blog.pythonlibrary.org/wp-content/uploads/2026/01/ty-pre-commit.png 1226w, https://blog.pythonlibrary.org/wp-content/uploads/2026/01/ty-pre-commit-300x157.png 300w, https://blog.pythonlibrary.org/wp-content/uploads/2026/01/ty-pre-commit-1024x535.png 1024w, https://blog.pythonlibrary.org/wp-content/uploads/2026/01/ty-pre-commit-768x401.png 768w" sizes="auto, (max-width: 1226px) 100vw, 1226px" /></p>
<p>Now, when you commit a file locally, pre-commit will run ty to check it for you automatically.</p>
<h2 class="header-anchor-post">Wrapping Up</h2>
<div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent">
<div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA">
<p><span style="font-size: 16px;">Type checkers can be really helpful in finding subtle bugs in your Python code. However, remembering to run them before pushing your code can be difficult, so make your life easier by adding the type checker to your CI!</span></p>
<p>&nbsp;</p>
</div>
</div>
<p>Have fun and happy coding!</p>
<p>The post <a href="https://blog.pythonlibrary.org/2026/01/09/how-to-switch-to-ty-from-mypy/">How to Switch to ty from Mypy</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>ANN: Vibe Coding Video Games with Python</title>
		<link>https://blog.pythonlibrary.org/2025/12/01/ann-vibe-coding-video-games-with-python/</link>
		
		<dc:creator><![CDATA[Mike]]></dc:creator>
		<pubDate>Mon, 01 Dec 2025 16:11:24 +0000</pubDate>
				<category><![CDATA[beginner]]></category>
		<category><![CDATA[Books]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[AI]]></category>
		<guid isPermaLink="false">https://blog.pythonlibrary.org/?p=12725</guid>

					<description><![CDATA[<p>I am happy to announce my latest book, Vibe Coding Video Games with Python. Here&#8217;s the announcement from my Kickstarter: Welcome to Vibe Coding Video Games with Python. In this book, you will learn how to use artificial intelligence to create mini-games. You will attempt to recreate the look and feel of various classic video [&#8230;]</p>
<p>The post <a href="https://blog.pythonlibrary.org/2025/12/01/ann-vibe-coding-video-games-with-python/">ANN: Vibe Coding Video Games with Python</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>I am happy to announce my latest book, <a href="https://www.kickstarter.com/projects/driscollis/vibe-coding-video-games-with-python">Vibe Coding Video Games with Python</a>. Here&#8217;s the announcement from my Kickstarter:</p>
<p>Welcome to <strong>Vibe Coding Video Games with Python</strong>. In this book, you will learn how to use artificial intelligence to create mini-games. You will attempt to recreate the look and feel of various classic video games. The intention is not to violate copyright or anything of the sort, but instead to learn the limitations and the power of AI.</p>
<p>Instead, you will simply be learning about whether or not you can use AI to help you know how to create video games. Can you do it with no previous knowledge, as the AI proponents say? Is it really possible to create something just by writing out questions to the ether?</p>
<p><strong>Release date: January 2026 (eBook) / March 2026 (paperback)</strong></p>
<p>You will be using various large language models (LLMs) such as Google Gemini, Grok, Mistral, CoPilot, and others to create these games. You will discover the differences and similarities between these tools. You may be surprised to find that some tools give much more context than others.</p>
<p>AI is certainly not a cure-all and is far from perfect. You will quickly discover AI&#8217;s limitations and learn some strategies for solving those kinds of issues.</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-12726 size-medium" src="https://blog.pythonlibrary.org/wp-content/uploads/2025/12/vibe_coding_cover-188x300.png" alt="" width="188" height="300" srcset="https://blog.pythonlibrary.org/wp-content/uploads/2025/12/vibe_coding_cover-188x300.png 188w, https://blog.pythonlibrary.org/wp-content/uploads/2025/12/vibe_coding_cover-642x1024.png 642w, https://blog.pythonlibrary.org/wp-content/uploads/2025/12/vibe_coding_cover-768x1225.png 768w, https://blog.pythonlibrary.org/wp-content/uploads/2025/12/vibe_coding_cover-963x1536.png 963w, https://blog.pythonlibrary.org/wp-content/uploads/2025/12/vibe_coding_cover-1283x2048.png 1283w, https://blog.pythonlibrary.org/wp-content/uploads/2025/12/vibe_coding_cover-scaled.png 1604w" sizes="auto, (max-width: 188px) 100vw, 188px" /></p>
<p>Here are some examples of what you will be creating in this book:</p>
<h4><strong>Lune Lander Clone</strong></h4>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-12727" src="https://blog.pythonlibrary.org/wp-content/uploads/2025/12/luna_lander.gif" alt="" width="792" height="626" /></p>
<h4>Asteroids Clone</h4>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-12728" src="https://blog.pythonlibrary.org/wp-content/uploads/2025/12/asteroids.gif" alt="" width="792" height="626" /></p>
<h4>Pong Clone</h4>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-12729" src="https://blog.pythonlibrary.org/wp-content/uploads/2025/12/pong.gif" alt="" width="802" height="626" /></p>
<h3><strong>What You&#8217;ll Learn</strong></h3>
<p>You&#8217;ll be creating &#8220;clones&#8221; of some popular games. However, these games will only be the first level and may or may not be fully functional.</p>
<ul>
<li>Chapter 1 &#8211; The Snake Game</li>
<li>Chapter 2 &#8211; Pong Clone</li>
<li>Chapter 3 &#8211; Frogger Clone</li>
<li>Chapter 4 &#8211; Space Invaders Clone</li>
<li>Chapter 5 &#8211; Minesweeper Clone</li>
<li>Chapter 6 &#8211; Luna Lander Clone</li>
<li>Chapter 7 &#8211; Asteroids Clone</li>
<li>Chapter 8 &#8211; Tic-Tac-Toe</li>
<li>Chapter 9 &#8211; Pole Position Clone</li>
<li>Chapter 10 &#8211; Connect Four</li>
<li>Chapter 11 &#8211; Intro to Sprites</li>
</ul>
<h3><strong>Rewards to Choose From</strong></h3>
<p>There are several different rewards you can get in this Kickstarter:</p>
<ul>
<li>A signed paperback copy of the book</li>
<li>An eBook copy of the book in PDF and ePub</li>
<li>A t-shirt with the cover art from the book</li>
<li>Other Python eBooks</li>
</ul>
<h2><a href="https://www.kickstarter.com/projects/driscollis/vibe-coding-video-games-with-python">Support the Kickstarter Today</a></h2>
<p>The post <a href="https://blog.pythonlibrary.org/2025/12/01/ann-vibe-coding-video-games-with-python/">ANN: Vibe Coding Video Games with Python</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Black Friday Python Deals Came Early</title>
		<link>https://blog.pythonlibrary.org/2025/11/18/black-friday-python-deals-came-early/</link>
					<comments>https://blog.pythonlibrary.org/2025/11/18/black-friday-python-deals-came-early/#comments</comments>
		
		<dc:creator><![CDATA[Mike]]></dc:creator>
		<pubDate>Tue, 18 Nov 2025 13:41:56 +0000</pubDate>
				<category><![CDATA[Books]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Black Friday]]></category>
		<guid isPermaLink="false">https://blog.pythonlibrary.org/?p=12721</guid>

					<description><![CDATA[<p>Black Friday deals came early this year. You can get 50% off of any of my Python books or courses until the end of November. You can use this coupon code at checkout: BLACKISBACK  The following links already have the discount applied: Python eBooks Python 101 Python 201: Intermediate Python The Python Quiz Book Automating [&#8230;]</p>
<p>The post <a href="https://blog.pythonlibrary.org/2025/11/18/black-friday-python-deals-came-early/">Black Friday Python Deals Came Early</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Black Friday deals came early this year. You can get 50% off of any of my Python books or courses until the end of November. You can use this coupon code at checkout: <strong>BLACKISBACK </strong></p>
<div style="width: 1200px;" class="wp-video"><video class="wp-video-shortcode" id="video-12721-1" width="1200" height="675" loop autoplay preload="metadata" controls="controls"><source type="video/mp4" src="https://blog.pythonlibrary.org/wp-content/uploads/2025/11/Black-friday-1.mp4?_=1" /><a href="https://blog.pythonlibrary.org/wp-content/uploads/2025/11/Black-friday-1.mp4">https://blog.pythonlibrary.org/wp-content/uploads/2025/11/Black-friday-1.mp4</a></video></div>
<p>The following links already have the discount applied:</p>
<h2>Python eBooks</h2>
<ul>
<li><a href="https://driscollis.gumroad.com/l/pypy101/blackisback">Python 101</a></li>
<li><a href="https://driscollis.gumroad.com/l/py201/blackisback">Python 201: Intermediate Python</a></li>
<li><a href="https://driscollis.gumroad.com/l/pyquiz/blackisback">The Python Quiz Book</a></li>
<li><a href="https://driscollis.gumroad.com/l/openpyxl/blackisback">Automating Excel with Python</a></li>
<li><a href="https://driscollis.gumroad.com/l/pylogging/blackisback">Python Logging</a></li>
<li><a href="https://driscollis.gumroad.com/l/pypillow/blackisback">Pillow: Image Processing with Python</a></li>
<li><a href="https://driscollis.gumroad.com/l/wxgui/blackisback">Creating GUI Applications with wxPython</a></li>
<li><a href="https://driscollis.gumroad.com/l/jupyterlab101/blackisback">JupyterLab 101</a></li>
<li><a href="https://driscollis.gumroad.com/l/textual/blackisback">Creating TUI Applications with Textual and Python</a></li>
</ul>
<h2>Python Courses</h2>
<ul>
<li><a href="https://driscollis.gumroad.com/l/pyvideo101/blackisback">Python 101 Video Series</a></li>
<li><a href="https://driscollis.gumroad.com/l/excel_bundle/blackisback">Automating Excel with Python Video series + eBook</a></li>
<li><a href="https://driscollis.gumroad.com/l/python_logging_course/blackisback">Python Logging Video Course</a></li>
</ul>
<p>&nbsp;</p>
<p>The post <a href="https://blog.pythonlibrary.org/2025/11/18/black-friday-python-deals-came-early/">Black Friday Python Deals Came Early</a> appeared first on <a href="https://blog.pythonlibrary.org">Mouse Vs Python</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.pythonlibrary.org/2025/11/18/black-friday-python-deals-came-early/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		<enclosure url="https://blog.pythonlibrary.org/wp-content/uploads/2025/11/Black-friday-1.mp4" length="1992530" type="video/mp4" />

			</item>
	</channel>
</rss>
