質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1543閲覧

【Python】'Nonetype' object has no attribute ~~ の直し方が分からない

ramurezun

総合スコア5

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/05/19 15:07

前提・実現したいこと

小林 郁夫・佐々木 晃共著の「Pythonによるプログラミング」p160の練習問題6.4に取り組んでいます。最終的にボールがブロックで跳ね返りブロックが消えるアニメーションを作成したいです。しかし、check_blocksのblockが正しく反映されません。自分でも挑戦してみましたが、上手くいきません。ご教授願います。

発生している問題・エラーメッセージ

Traceback (most recent call last):
File "C:\Users\user\Desktop\python\ex06-block.py", line 182, in <module>
box.animate()
File "C:\Users\user\Desktop\python\ex06-block.py", line 162, in animate
self.check_blocks(self.ball,self.block)
File "C:\Users\user\Desktop\python\ex06-block.py", line 145, in check_blocks
if(block.y<ball.y+ball.d/2<block.y+block.h
AttributeError: 'NoneType' object has no attribute 'y'

該当のソースコード

from tkinter import * from dataclasses import dataclass,field import time @dataclass class Ball: id:int x:int y:int d:int vx:int vy:int c:str="black" def move(self): self.x=self.x+self.vx self.y=self.y+self.vy def redraw(self): d=self.d canvas.coords(self.id,self.x,self.y, self.x+d,self.y+d) @dataclass class Paddle: id:int x:int y:int w:int h:int vy:int = field(init=False,default=0) c:str="green" def move(self): self.y=self.y+self.vy def redraw(self): canvas.coords(self.id,self.x,self.y, self.x+self.w,self.y+self.h) def set_v(self,v): self.vy=v def stop(self): self.vy=0 @dataclass class Block: id:int x:int y:int w:int h:int c:str def redraw(self): canvas.coords(self.id,self.x,self.y, self.x+self.w,self.y+self.h) def delete(self): canvas.delete(self.id) @dataclass class Box: id:int west:int north:int east:int south:int ball:Ball paddle:Paddle block:Block paddle_v:int duration:float def __init__(self,x,y,w,h,duration): self.west,self.north=(x,y) self.east,self.south=(x+w,y+h) self.ball=None self.paddle=None self.block=None self.blocks=[] self.duration=duration self.paddle_v=5 def make_ball(self,x,y,d,vx,vy): id=canvas.create_oval(x,y,x+d,y+d, fill="black",outline="black") return Ball(id,x,y,d,vx,vy) def make_walls(self): canvas.create_rectangle(self.west,self.north,self.east,self.south) def check_wall(self,ball): if ball.x+ball.vx<=self.west or ball.x+ball.d+ball.vx>=self.east: ball.vx=-ball.vx if ball.y+ball.vy<=self.north or ball.y+ball.d+ball.vy>=self.south: ball.vy=-ball.vy def set_ball(self): self.ball=self.make_ball(self.west+10,self.north+10,10,4,2) def make_paddle(self,x,y,w,h,c): id=canvas.create_rectangle(x,y,x+w,y+h, fill=c,outline=c) return Paddle(id,x,y,w,h) def check_paddle(self,ball,paddle): if(ball.y+ball.d/2>=paddle.y and paddle.x<=ball.x+ball.d and ball.y+ball.d/2<=paddle.y+paddle.h): ball.vx=-ball.vx def set_paddle(self): self.paddle=self.make_paddle(self.east-20,(self.north+self.south)/2-10, 10,20, "green") def up_paddle(self,event): self.paddle.set_v(-self.paddle_v) def down_paddle(self,event): self.paddle.set_v(self.paddle_v) def stop_paddle(self,event): self.paddle.stop() def make_block(self,x,y,w,h,c): id=canvas.create_rectangle(x,y,x+w,y+h, fill=c,outline=c) return Block(id,x,y,w,h,c) def set_blocks(self,n,s): for x in range(n): block=self.make_block(self.west+10*x,self.south-30, 5,20,"red") for x in range(s): block=self.make_block(self.west+10*x,self.south-60, 5,20,"blue") self.blocks.append(block) def check_blocks(self,ball,block): if(block.y<ball.y+ball.d/2<block.y+block.h and(block.x<=ball.x<=block.x+block.w or block.x<=ball.x+ball.d<=block.x+block.w)): ball.vx=-ball.vx self.block.delete() self.blocks.remove() def animate(self): while True: self.ball.move() self.paddle.move() self.check_wall(self.ball) self.check_paddle(self.ball,self.paddle) self.ball.redraw() self.paddle.redraw() for block in self.blocks: self.check_blocks(self.ball,self.block) self.block.redraw() time.sleep(self.duration) tk.update() tk=Tk() canvas=Canvas(tk,width=800,height=800,bd=0) canvas.pack() box=Box(100,100,300,200,0.05) box.make_walls() canvas.bind_all("<KeyPress-Up>",box.up_paddle) canvas.bind_all("<KeyPress-Down>",box.down_paddle) canvas.bind_all("<KeyRelease-Up>",box.stop_paddle) canvas.bind_all("<KeyRelease-Down>",box.stop_paddle) box.set_ball() box.set_paddle() box.set_blocks(4,4) box.animate()

試したこと

補足情報(FW/ツールのバージョンなど)

以下、該当ページを掲載します。
https://books.google.co.jp/books?id=sOKxDwAAQBAJ&pg=PA161&lpg=PA161&dq=python%E3%81%AB%E3%82%88%E3%82%8B%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%80%80%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB&source=bl&ots=nzXmB2DTmb&sig=ACfU3U1g0d42R2WQQ01Qg8LVyYfn6I3iKg&hl=ja&sa=X&ved=2ahUKEwjA1dXmh8DpAhW_x4sBHbmRB9wQ6AEwBXoECAkQAQ#v=onepage&q=python%E3%81%AB%E3%82%88%E3%82%8B%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%80%80%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB&f=false
コード

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

for block in self.blocks:

self.check_blocks(self.ball,self.block) self.block.redraw()

check_blockを呼び出しているところ。
for のローカル変数じゃなく、クラス変数のself.blockを引数に与えているが、これであってるの?

投稿2020/05/19 15:33

y_waiwai

総合スコア88042

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

teamikl

2020/05/20 03:17 編集

他にも、いくつか self.blockを使っている箇所の修正が必要そうですが。 Noneオブジェクトが渡されている原因はここみたいですね。self.block -> block redraw, delete の修正と self.blocks.remove(block) で動作確認。 (※赤いブロックのリージョン判定はされてませんでした) ちなみに、本題と関係ありませんが、self.block はインスタンス変数に相当します。 dataclasses.dataclass デコレータを使っていて、従来のクラス変数を書くところに、 フィールド宣言(っぽいもの)を書けるようになりました。
ramurezun

2020/05/20 12:51

redraw,check,deleteのself.blockをblockにすることで解決しました。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問