小能豆

Flask 问题 TypeError: object.__new__() takes exactly one argument (the type to instantiate)

python

问题 :

cls._instance = super(MateDealer, cls).__new__(cls, *args, **kwargs)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
sc = SessionController(db, User, Product, Vend)
import sys
import os
import re
from datetime import datetime, timedelta
import time
from flask_serial import Serial
from threading import Thread

class SessionController:

    def __init__(self, db, user, product, vend):
        self.db = db
        self.timer = None
        self._lock = False
        self.product = product
        self.vend = vend
        self.user = user
        self.active_user = ""
        self.md = MateDealer(self)
        self.md.start()
        self.user_id = None

    def is_locked(self):
        return self._lock

    def vend_start(self, user_id):
        self.user_id = user_id
        self.lock()
        user = self.user.query.get(self.user_id)
        self.active_user = user.name 
        self.md.start_session(user.balance)

    def vend_request(self, item):
        product = self.product.query.filter_by(slot=item).first()
        print (product)
        user = self.user.query.get(self.user_id)
        print (user)
        if user.balance >= product.price:
            self.md.approve_vend(product.price)
        else:
            self.md.deny_vend()

    def vend_success(self, item):
        product = self.product.query.filter_by(slot=item).first()
        product.stock -= 1
        user = self.user.query.get(self.user_id)
        user.balance -= product.price
        vend = self.vend(user.name, product.name, product.price, datetime.now())
        self.db.session.add(vend)
        self.db.session.commit()
        self.cancel()

    def lock(self):
        self._lock = True

    def unlock(self):
        self._lock = False

    def cancel(self):
        if self.timer != None:
            self.timer.stop()
            self.timer = None
        self.active_user = ""
        self.unlock()
        self.md.cancel_session()


class Timer(Thread):

    def __init__(self, time, callback):
        Thread.__init__(self)
        self.time = time
        self.callback = callback
        self.canceled = False

    def run(self):
        while self.time > 0 and not self.canceled:
            time.sleep(1)
            self.time -= 1

        if not self.canceled:
            self.callback()

    def stop(self):
        self.canceled = True


class MateDealer(Thread):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(MateDealer, cls).__new__(cls, *args, **kwargs)
        return cls._instance

    def __init__(self, sc, *args, **kwargs):
        Thread.__init__(self)
        self.sc = sc
        self.serial = Serial()
        self.serial.port = '/dev/ttyACM0'
        self.serial.baudrate = 38400
        self.serial.bytesize = 8
        self.serial.parity = 'N'
        self.serial.stopbits = 1
        self.serial.timeout = 0.1
        self.running = False

    def run(self):
        try:
            self.serial.open()
        except Exception as e:
            print >> sys.stderr, e.message
            return

        print (self.serial)
        self.running = True
        msg = ''
        while self.running:
            byte = self.serial.read()
            if byte != '':
                msg += byte
            if msg.endswith('\n'):
                self.parse_cmd(msg)
                msg = ''

        if self.serial.is_open():
            self.serial.close()

    def start_session(self, balance):
        self.serial.write('start-session %d\r\n' % balance)
        print ('start-session %d' % balance)

    def approve_vend(self, price):
        self.serial.write('approve-vend %d\r\n' % price)
        print ('approve-vend %d\r\n' % price)

    def deny_vend(self):
        self.serial.write('deny-vend\r\n')
        print ('deny-vend')

    def cancel_session(self):
        self.serial.write('cancel-session\r\n')
        print ('cancel-session')

    def parse_cmd(self, cmd):
        cmd = cmd.strip()
        if cmd.startswith('vend-request'):
            _cmd, price, item = cmd.split(' ')
            self.sc.vend_request(item)
        elif cmd.startswith('vend-success'):
            _cmd, item = cmd.split(' ')
            self.sc.vend_success(item)
        elif cmd.startswith('session-complete'):
            self.sc.cancel()
        else:
            print (cmd)

用 python 2 改变

         cls._instance = super(MateDealer, cls).__new__(cls, *args, **kwargs)

我删除了它和 python3

         cls._instance = super().__new__()

我试过了,但没用


阅读 106

收藏
2023-06-06

共2个答案

小能豆

在Python 2中,您可以将代码修改为以下方式以实现与原始代码中的__new__方法相同的行为:

cls._instance = super(MateDealer, cls).__new__(cls, *args, **kwargs)

修改后的代码如下:

cls._instance = super(MateDealer, cls).__new__(cls, *args, **kwargs)

然而,在Python 3中,super()语法略有不同,您可以将其修改为以下方式:

cls._instance = super().__new__(cls)

请注意,super()函数在Python 3中不需要传递cls*args**kwargs参数。它会自动识别并调用正确的父类构造函数。

如果您在Python 3中修改了代码,但问题仍然存在,请提供完整的错误消息和堆栈跟踪,以便我可以更好地帮助您解决问题。

2023-06-06
小能豆

在 Python 3 中,您不需要将任何其他参数传递给调用__new__,因此您需要:

cls._instance = super().__new__(cls)

尽管请注意,您的实施的一个潜在问题是

 __init__

每次你打电话时都会再次运行MateDealer()......我推测这不是你想要的,因为你似乎正在尝试创建某种单身人士。你在这里做什么的目的到底是什么?

如果您只是想要一个“单身人士”,那么甚至不必为所有这些烦恼。只需定义一个缓存实例的工厂函数和一个“私有”类,如此快速和肮脏:

class _MateDealer(Thread):
    def __init__(self, sc, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.sc = sc
        self.serial = Serial()
        self.serial.port = '/dev/ttyACM0'
        self.serial.baudrate = 38400
        self.serial.bytesize = 8
        self.serial.parity = 'N'
        self.serial.stopbits = 1
        self.serial.timeout = 0.1
        self.running = False

__instance = None

def MateDealer(sc, *args, **kwargs):
    global __instance
    if __instance is None:
        __instance = _MateDealer(sc, *args, **kwargs)
    return _mate_instance
2023-06-06