多维Python dict上的数学运算

2024-04-27 03:41:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在移植PHP中的一些代码,这些代码遍历一些数据库结果,并为棒球联盟中的球队构建一个二维的胜负数组。下面是有问题的PHP代码

    foreach ($results as $result) {
        $home_team = $result['Game']['home_team_id'];
        $away_team = $result['Game']['away_team_id'];

        if (!isset($wins[$home_team][$away_team])) $wins[$home_team][$away_team] = 0;
        if (!isset($wins[$away_team][$home_team])) $wins[$away_team][$home_team] = 0;
        if (!isset($losses[$home_team][$away_team])) $losses[$home_team][$away_team] = 0;
        if (!isset($losses[$away_team][$home_team])) $losses[$away_team][$home_team] = 0;

        if ($result['Game']['home_score'] > $result['Game']['away_score']) {
            $wins[$home_team][$away_team]++;
            $losses[$away_team][$home_team]++;
        } else {
            $wins[$away_team][$home_team]++;
            $losses[$home_team][$away_team]++;
        }
    }

$results是包含数据库查询结果的数组

(编辑后添加了我在profess中的Python代码)

现在我用Python写了这个。results包含Sqlalchemy结果对象的集合

from sqlalchemy import Column, create_engine, ForeignKey, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker


Base = declarative_base()
engine = create_engine('postgresql://stats:st@ts=Fun@localhost/ibl_stats')
Session = sessionmaker()
Session.configure(bind=engine)
session = Session()


class Game(Base):
    __tablename__ = 'games'

    id = Column(Integer, primary_key=True)
    week = Column(Integer)
    home_score = Column(Integer)
    away_score = Column(Integer)
    home_team_id = Column(Integer, ForeignKey('franchises.id'))
    away_team_id = Column(Integer, ForeignKey('franchises.id'))


class Franchise(Base):
    __tablename__ = 'franchises'

    id = Column(Integer, primary_key=True)
    nickname = Column(String(3))
    name = Column(String(50))
    conference = Column(String(10))
    division = Column(String(10))
    ip = Column(Integer)

# Loop through our standings building up the breakdown results
results = session.query(Game).all()
wins = dict()
losses = dict()

for result in results:
    home_team = result.home_team_id
    away_team = result.away_team_id

    if result.home_score > result.away_score:
        wins[home_team][away_team] += 1
        losses[away_team][home_team] += 1
    else:
        wins[away_team][home_team] += 1
        losses[home_team][away_team] += 1

因此,当我运行此代码时,会出现以下错误:

(venv)vagrant@ibl:/vagrant/scripts$ python playoff_odds.py
Traceback (most recent call last):
  File "playoff_odds.py", line 45, in <module>
    wins[home_team][away_team] += 1
KeyError: 1

我之前做过一些搜索,它开始进入“autovivification”的概念,这是PHP默认做的,而Python没有。你知道吗

那么如何在Python代码中复制相同的行为呢?你知道吗


Tags: 代码idgamehomestringifcolumninteger
3条回答

这个问题有许多解释。例如,我将使用以下字典模拟结果:

>>> result = {'Game':{'home_team':{'score':20,'id':1}, 'away_team':{'score':15,'id':2}}}
>>> print result['Game']
{'home_team': {'score': 20, 'id': 1}, 'away_team': {'score': 15, 'id': 2}}
>>> print result['Game']['home_team']
{'score': 20, 'id': 1}
>>> print result['Game']['away_team']['score']
15

有很多方法可以模拟你的代码,以上只是其中之一。当然,代码并不像php代码那样,只是显示了一种访问数据的方法。你知道吗

Python's built-in dict class can be subclassed to implement autovivificious dictionaries simply by overriding the missing() method ,但这只是解决方案的一部分。如果您只需在Wikipedia链接中实现Tree示例并执行以下操作:

wins = Tree()

wins['team_a']['team_b'] += 1

您会遇到:TypeError: unsupported operand type(s) for +=: 'Tree' and 'int',因为wins['team_a']['team_b']示例代码也会自动键入Tree。你知道吗

鉴于:

wins = Tree()

wins['team_a']['team_b'] = 1

将正确地赋值1(因为这是一个重新赋值,而不是对现有类型化值的操作)。你知道吗

该解决方案将子类化,以实现autovivification,确保叶元素是可以对其进行操作的整数。你知道吗

以下内容应该会有所帮助,或者至少可以让您开始学习:

from collections import defaultdict

def autovivify(levels=1, final=dict):
    return (defaultdict(final) if levels < 2
        else defaultdict(lambda: autovivify(levels - 1, final)))

wins = autovivify(2, int)
losses = autovivify(2, int)

wins['team_a']['team_b'] += 1
losses['team_b']['team_a'] += 1

wins['team_b']['team_c'] += 1
losses['team_c']['team_b'] += 1

wins['team_a']['team_c'] += 1
losses['team_c']['team_a'] += 1

wins['team_a']['team_b'] += 1
losses['team_b']['team_a'] += 1

print(wins['team_a']) # outputs defaultdict(<type 'int'>, {'team_b': 2, 'team_c': 1})

来源:http://blogs.fluidinfo.com/terry/2012/05/26/autovivification-in-python-nested-defaultdicts-with-a-specific-final-type/

autovify函数将确保第一个赋值(team_a)将为您提供另一个autovify树,第二个赋值(team_b)将为您提供一个整数。从那里开始,+= 1将继续增加0的初始值。你知道吗

我想我可能会在这里使用namedtuples,但是仅仅从这个片段很难判断。你知道吗

如果您想了解如何编写更多的Pythonic代码,我建议您查看raymondhettinger的视频,尤其是

“美观易懂代码的最佳实践”和 “将代码转换为漂亮、惯用的Python”:

http://pyvideo.org/speaker/raymond-hettinger.html

相关问题 更多 >