创建具有大量变量的类的正确方法 输出

如何解决创建具有大量变量的类的正确方法 输出

我在多年没有这样做之后最近开始编码,我正在构建一个小项目以重新开始。这是一个使用各种加密交易市场专用 API 的小型应用程序。

我的问题不是解决问题,而是解决问题的正确方法。因为我不喜欢有很多变量的编码模型,所以我决定创建一个抽象模型来为我完成定义变量的劳动密集型部分。

问题来了。创建一个需要很多变量的类时,我应该:

  1. 定义 __init__() 方法中的每个变量,并在 __init__() 标头中包含每个变量

  2. 我可以使用我的抽象类,它只需要定义所需的变量列表吗?我可以在未来的项目中做到这一点吗?

我的抽象类使用变量名的“静态”列表(我知道是 Python)并实现了构建动态/抽象对象的 __init__(self,*args,**kwargs) 方式。

我不知道应该为项目实现显式的笨重方法还是隐式的抽象方法。人们/团队在现实世界中使用的标准方法是什么?

示例

显式庞大方法

class Coin(object):
    def __init__(self,id=None,base_currency=None,quote_currency=None,base_min_size=None,base_max_size=None,quote_increment=None,base_increment=None,display_name=None,min_market_funds=None,max_market_funds=None,margin_enabled=None,post_only=None,limit_only=None,cancel_only=None,trading_disabled=None,status=None,status_message=None):
    self.id = id
    self.base_currency = base_currency
    self.quote_currency = quote_currency
    self.base_min_size = base_min_size
    self.base_max_size = base_max_size
    self.quote_increment = quote_increment
    self.base_increment = base_increment
    self.display_name = display_name
    self.min_market_funds = min_market_funds
    self.max_market_funds = max_market_funds
    self.margin_enabled = margin_enabled
    self.post_only = post_only
    self.limit_only = limit_only
    self.cancel_only = cancel_only
    self.trading_disabled = trading_disabled
    self.status = status
    self.status_message = status_message

隐式抽象方法

class EasyModel(object):
    """ Abstract Model. Use to create models that might have extensive variable members,or in cases where applicable. """

    __attrs__ = []

    def __init__(self,**kwargs):
        self.set_using_args(args) # set variables given as a *args
        self.set_using_kwargs(kwargs) # set variables given as **kwargs
        self.fill_empty() # Set variables that were expected to None

    def set_using_args(self,args):
        """ Given a list of variables (assuming in the correct order),add the value to the proper variable name. """
        for i,arg_value in enumerate(args):
            arg_name = self.__class__.__attrs__[i]
            setattr(self,arg_name,arg_value)

    def set_using_kwargs(self,kwargs):
        """ Given a dictionary,add the parameters as variables to the instance if the parameter is valid. """
        for arg_name,arg_value in kwargs.items():
            if (arg_name in self.__class__.__attrs__):
                setattr(self,arg_value)

    def fill_empty(self):
        """ Create any undefined variables and set as None """
        for arg_name in self.__class__.__attrs__:
            if (not hasattr(self,arg_name)):
                setattr(self,None)

    def __setattr__ (self,name,value):
        """ Make sure that the attributes that will be added are expected. """
        if (name in self.__class__.__attrs__):
            self.__dict__[name] = value


class Coin(EasyModel):
    """ Using the EasyModel to quickly build a model that will be created from an API request that gives all the data below in the form of a dictionary. """

    __attrs__ = ['id','base_currency','quote_currency','base_min_size','base_max_size','quote_increment','base_increment','display_name','min_market_funds','max_market_funds','margin_enabled','post_only','limit_only','cancel_only','trading_disabled','status','status_message']

    def __init__(self,**kwargs):
        super(Coin,self).__init__(*args,**kwargs)

# Both would result in the same usage.
coin_data = {...} # Json / dictionary version of object

# Create object by passin json / dictionary as **kwargs
c = Coin(**coin_data)

# Both methods would result in this usage.
print (c.display_name)

解决方法

这最终比我想象的要难。我几乎没有触及元类和数据类的表面,但这是我想出的解决方案,包括最后的工作演示。

我不确定我会坚持哪种解决方案。

# Required for dataclass
from dataclasses import dataclass

# Required to get coin data used in example.
import cbpro
    
""" Resources Used: 
https://www.geeksforgeeks.org/__new__-in-python/
https://www.pythonpool.com/python__new__/

I dont speak or read japanese but i found the snippets to be helpful.
https://python.ms/new/#_3-super-%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B%E3%80%82
"""    

############################################################################################################    
       
class CoinFunctions(object):
   """ A class of functionalities for a coin. All the class varients will inheirt this class. """

   def get_base_currency(self):
       return self.base_currency
   
############################################################################################################        
   
def create_coin(data):
   """ Dynamically Create a type/class and apply the CoinFunctions's methods. """
   
   coin_class = type("GeneratedCoin",(CoinFunctions,),data) # Build a new class. Still needs to be initialized
   c = coin_class()
   c.__dict__ = data
   return c  # Return an object initialized from the generated class.

############################################################################################################

class MetaCoin(CoinFunctions):
   """ class that implements the __new__ method. Haven't got into inheriting from metaclasses yet. """
   
  # Constructs the object to be initialized
   def __new__(cls,**kwargs):
       self = object.__new__(cls)
       self.__dict__ = kwargs
       return self # Returns the object 

   # Initializes the object.
   def __init__(self,*args,**kwargs):
       pass
   
############################################################################################################       

@dataclass()
class Coin(CoinFunctions):
   """ A dataclass that is used to build a proper data set of a coin with built-in types. Inherit from CoinFunctions for functionalities"""
   
   id : str # base_currency-quote_currency (LTC-BTC)
   base_currency : str # (LTC)
   quote_currency : str # (BTC)
   base_min_size : str # float
   base_max_size : str # int / float
   quote_increment : str # double
   base_increment : str # double
   display_name : str
   min_market_funds : str # float
   max_market_funds : str # int / float
   margin_enabled : bool
   post_only : bool
   limit_only : bool
   cancel_only : bool
   trading_disabled : bool
   status : str
   status_message : str
    
############################################################################################################


""" 
This is my original solution. 

The __attrs__ field accepts a list of names that will be variables of the class.
The list of names that is __attrs__ are not only made into variables but are the only allowed variables.
If you want a variable in your class you must include its name inside of __attrs__.

When inheriting from EasyModel the only required ovveride is the __attrs__ field.
"""

class EasyModel(object):
   """ Abstract Model. Use to create models that might have extensive variable members,or in cases where applicable. """
   
   __attrs__ = []
   
   def __init__(self,**kwargs):
       self.set_using_args(args) # set variables given as a *args
       self.set_using_kwargs(kwargs) # set variables given as **kwargs
       self.fill_empty() # Set variables that were expected to None

   def set_using_args(self,args):
       """ Given a list of variables (assuming in the correct order),add the value to the proper variable name. """
       #print (self.__class__.__attrs__)
       for i,arg_value in enumerate(args):
           #print ("\n\n********* WORKING IN ARGS *********\n\n")
           arg_name = self.__class__.__attrs__[i]
           setattr(self,arg_name,arg_value)
               
   def set_using_kwargs(self,kwargs):
       """ Given a dictionary,add the parameters as variables to the instance if the parameter is valid. """
       for arg_name,arg_value in kwargs.items():
           #print (arg_name in self.__class__.__attrs__)
           if (arg_name in self.__class__.__attrs__):
               setattr(self,arg_value)
       
   def fill_empty(self):
       """ Create any undefined variables and set as None """
       for arg_name in self.__class__.__attrs__:
           if (not hasattr(self,arg_name)):
               setattr(self,None)
           
   def __setattr__ (self,name,value):
       """ Make sure that the attributes that will be added are expected. """
       if (name in self.__class__.__attrs__):
           self.__dict__[name] = value
           




class EasyCoin(EasyModel):
   """ Using the EasyModel to quickly build a model that will be created from an API request that gives all the data below in the form of a dictionary. """ 

   __attrs__ = ['id','base_currency','quote_currency','base_min_size','base_max_size','quote_increment','base_increment','display_name','min_market_funds','max_market_funds','margin_enabled','post_only','limit_only','cancel_only','trading_disabled','status','status_message']
 
   def __init__(self,**kwargs):
       super(EasyCoin,self).__init__(*args,**kwargs)
       
       




       
#########################################################################################################################################
#########################################################################################################################################

# Executing The Code: 
if __name__ == '__main__':
   
   # Make a connection to coinbase pro and request a list of their crypto trade markets.
   client = cbpro.PublicClient()
   
   #list_of_coins = client.get_currencies() # an actual list of coins
   list_of_coins = client.get_products() # a list of supported crypto trades. 
   
   
    
   # Each item in the list_of_coins is a dictionary. 
   for coin_data in list_of_coins:
       
       c = create_coin(coin_data)
       
       print ("")
       print ("Type:",type(c))
       print ("Class Bases:",c.__class__.__bases__)
       print ("Object:",c)
       print ("Object.__dict__",c.__dict__)
       
       c = MetaCoin(**coin_data)
       
       print ("")
       print ("Type:",c.__dict__)        
              
       c = Coin(**coin_data)
       
       print ("")
       print ("Type:",c.__dict__)
       
       c = EasyCoin(**coin_data) 

       print ("")
       print ("Type:",c.__dict__)
       
       break        
   

输出

Type: <class '__main__.GeneratedCoin'>
Class Bases: (<class '__main__.CoinFunctions'>,)
Object: <__main__.GeneratedCoin object at 0x043867D0>
Object.__dict__ {'id': 'LINK-USD','base_currency': 'LINK','quote_currency': 'USD','base_min_size': '0.1','base_max_size': '90000','quote_increment': '0.00001','base_increment': '0.01','display_name': 'LINK/USD','min_market_funds': '10','max_market_funds': '100000','margin_enabled': False,'post_only': False,'limit_only': False,'cancel_only': False,'trading_disabled': False,'status': 'online','status_message': ''}

Type: <class '__main__.MetaCoin'>
Class Bases: (<class '__main__.CoinFunctions'>,)
Object: <__main__.MetaCoin object at 0x04386730>
Object.__dict__ {'id': 'LINK-USD','status_message': ''}

Type: <class '__main__.Coin'>
Class Bases: (<class '__main__.CoinFunctions'>,)
Object: Coin(id='LINK-USD',base_currency='LINK',quote_currency='USD',base_min_size='0.1',base_max_size='90000',quote_increment='0.00001',base_increment='0.01',display_name='LINK/USD',min_market_funds='10',max_market_funds='100000',margin_enabled=False,post_only=False,limit_only=False,cancel_only=False,trading_disabled=False,status='online',status_message='')
Object.__dict__ {'id': 'LINK-USD','status_message': ''}

Type: <class '__main__.EasyCoin'>
Class Bases: (<class '__main__.EasyModel'>,)
Object: <__main__.EasyCoin object at 0x043867D0>
Object.__dict__ {'id': 'LINK-USD','status_message': ''}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res