2016-06-27 1 views
1

Ниже приведена неполная реализация для Game Of Life от Conway в Python 3.0 с использованием Tkinter в PyCharm Community Edition.Получение типаError: object .__ new __() не принимает параметров, когда __new__ не изменен

Программа состоит из четырех файлов:

  • Cell.py: Содержит класс для ячейки
  • Grid.py: Содержит класс для игры Life Grid
  • Windows.py: Содержит класс для Tkinter макета
  • main.py: выполняет скрипт

Cell.py:

from random import randint 
from tkinter import * 

class Cell: 
    def __init__(self, master, state=None): 
     if state is None: 
      state = randint(0,2) 
     self.state = state 
     self.next_state = state 
     self.button = Button(master, width=2, height=1, bg = 'black' if self.state == 1 else 'white').pack(side=LEFT) 

    def __del__(self): 
     self.button.destroy() 

    def set_next_state(self, neighbours): 
     if self.state == 1: 
      self.next_state = 0 if neighbours < 2 or neighbours > 3 else 1 
     else: 
      self.next_state = 1 if neighbours == 3 else 0 

    def update(self): 
     self.state = self.next_state 
     self.button.config(bg = 'black' if self.state == 1 else 'white') 

Grid.py:

from tkinter import * 
from Cell import Cell 

class Grid: 
    def __init__(self, master, rows=15, cols=15, wraparound=True, pattern=None): 
     self.master = master 
     self.rows = rows 
     self.cols = cols 
     self.wraparound = wraparound 

     if len(self.pattern) == rows*cols: self.pattern = pattern 
     else: self.pattern = None 

     self.create_frames() 
     self.create_cells() 

    def create_frames(self): 
     self.frames = [Frame(self.master).pack(side=TOP) for r in range(self.rows)] 

    def destroy_frames(self): 
     for r in range(self.rows): 
      self.frames[r].destroy() 

    def create_cells(self): 
     self.cells = {} 
     for r in range(self.rows): 
      for c in range(self.cols): 
       if self.pattern is None: self.cells[(r,c)] = Cell(self.frames[r]) 
       else: self.cells[(r,c)] = Cell(self.frames[r], state=self.pattern[r*self.cols+c]) 

    def destroy_cells(self): 
     for r in range(self.rows): 
      for c in range(self.cols): 
       del self.cells[(r,c)] 

    def count_neighbours(self, r, c): 
     offsets = [(i,j) for j in range(-1,2) for i in range(-1,2)] 
     offsets.remove((0,0)) 
     neighbours = 0 
     for offset in offsets: 
      if self.wraparound: 
       neighbours += self.cells[((r+offset[0])%self.rows, (c+offset[1])%self.cols)].state 
      else: 
       if r+offset[0] >= self.rows or r+offset[0] < 0 or c+offset[1] >= self.cols or c+offset[1] < 0: 
        neighbours += 0 
       else: 
        neighbours += self.cells[(r+offset[0], c+offset[1])].state 
     return neighbours 

    def calculate_next_state(self): 
     for r in range(self.rows): 
      for c in range(self.cols): 
       neighbours = self.count_neighbours(r,c) 
       self.cells[(r,c)].set_next_state(neighbours) 

    def update_cells(self): 
     for r in range(self.rows): 
      for c in range(self.cols): 
       self.cells[(r,c)].update() 

    def step(self): 
     self.calculate_next_state() 
     self.update_cells() 

    def load_pattern(self, rows=10, cols=10, wraparound=True, pattern=None): 
     self.destroy_cells() 
     self.destroy_frames() 

     self.rows = rows 
     self.cols = cols 
     self.wraparound = wraparound 
     self.pattern = pattern 

     self.create_frames() 
     self.create_cells() 

Windows.py:

from Grid import Grid 
from tkinter import * 

class MainWindow: 
    def __init__(self, rows=10, cols=10, wraparound=True, pattern=None): 
     self.root = Tk() 

     grid_frame = Frame(self.root).pack(side=TOP) 
     self.grid = Grid(grid_frame, rows=rows, cols=cols, wraparound=wraparound, pattern=pattern) 

     button_frame = Frame(self.root).pack(side=BOTTOM) 
     self.time_interval = 1000 
     self.start_stop_button = Button(button_frame, text='START', command=self.start_stepper).pack(side=LEFT) 
     self.step_button = Button(button_frame, text='STEP', command=self.grid.step) 

     self.menubar = Menu(self.root) 
     self.menubar.add_command(label='Change Time Interval', command=self.change_time_interval) 
     self.root.config(menu=self.menubar) 

     self.root.mainloop() 

    def change_time_interval(self): 
     # Incomplete 
     pass 

    def start_stepper(self): 
     # Incomplete 
     pass 

    def stop_stepper(self): 
     # Incomplete 
     pass 

main.py:

from Windows import MainWindow 
game = MainWindow() 

Когда я бегу main.py я получаю следующий результат :

Выход:

Traceback (most recent call last): 
    File "C:/Users/Tyler/PycharmProjects/GameOfLife/main.py", line 3, in <module> 
    game = MainWindow() 
    File "C:\Users\Tyler\PycharmProjects\GameOfLife\Windows.py", line 9, in __init__ 
    self.grid = Grid(grid_frame, rows=rows, cols=cols, wraparound=wraparound, pattern=pattern) 
TypeError: object.__new__() takes no parameters 

Я на моем конце остроумии с этим, как я никогда не перезаписывать по умолчанию метода __new__. После проверки всех других вопросов переполнения стека этого типа большинство решений исправляло некоторую форму написания __init__ до __init__. Я относительно новичок в написании сценариев python, поэтому любая помощь, чтобы отладить это с объяснением причин возникновения ошибки, была бы наиболее оценена.

+0

Все ваши проблемы исходят из * переопределения * класса 'Tkinter.Grid()'. Затем вам нужно переименовать класс 'Grid()' в нечто другое. –

ответ

4

У Tkinter есть класс Grid, который затеняет ваш собственный класс с тем же именем, потому что вы использовали from tkinter import * после импорта собственного класса.

Есть несколько возможных решений:

  1. Изменить свой импорт в from Grid import Grid as MyGrid, а затем вызвать MyGrid, если вы хотите использовать свой собственный класс Grid.
  2. Импортируйте свой from Grid import Grid импорт после tkinter one (при условии, что вам не нужно использовать класс tkinter Grid).
  3. Изменение импорта Tkinter в import tkinter и доступа классов Tkinter (например, Frame) с tkinter.Frame и т.д.
  4. Изменить имя вашего класса к чему-то еще.
+0

Как всегда задним числом это кажется настолько очевидным. Большое спасибо. – Chubzorz

+1

И поэтому вы не используете 'import *', даже для tkinter. – user2357112

+1

@Chubzorz Общей практикой является «import tkinter as tk». Пожалуйста, см. Http://stackoverflow.com/a/37511018/4014959 по другим причинам, чтобы избежать импорта звезд. –

Смежные вопросы