Python - AttributeError: 'function' object has no attribute 'rank'
Python - AttributeError: 'function' object has no attribute 'rank'
我正在通过自己编写代码和观看 Youtube videos.
来解决不同的 Project Euler 问题
在处理问题 54 时,Youtube 视频的作者在 Python 2.7 中定义函数时编写的代码是
def __init__(self, *args):
self.cards = sorted(args, key=lambda c: -c.rank)
self.duplicates = {}
for card in self.cards:
if card.rank in self.duplicates:
continue
_duplicates = 0
for card2 in self.cards:
if card.rank == card2.rank:
_duplicates += 1
self.duplicates[card.rank] = _duplicates
这对他来说似乎很管用。当我在 Python 3.0 上 运行 这段代码时,我的 Pycharm 编译器 returns
File "C:/Users/Matthew/PycharmProjects/Project_Euler/Euler54.py", line 51, in __init__
self.cards = sorted(args, key=lambda c: -c.rank)
File "C:/Users/Matthew/PycharmProjects/Project_Euler/Euler54.py", line 51, in <lambda>
self.cards = sorted(args, key=lambda c: -c.rank)
AttributeError: 'function' object has no attribute 'rank'
我试过改变
self.cards = sorted(args, key=lambda c: -c.rank)
到
self.cards = sorted(args, key=lambda c: -c.rank())
但这似乎是一个不正确的修复。我不确定如何自行解决此错误。我可以考虑编写一个不同的解决方案,因为视频作者展示的策略对初学者来说并不友好。完整的程序粘贴在下面(我不确定是否应该包括这个,因为我没有正式寻找代码审查。我试图让程序达到 运行 以便我可以完成练习).
import time
from collections import namedtuple
start = time.time()
Card = namedtuple('Card', ['rank', 'suit'])
Ace = 14
King = 13
Queen = 12
Jack = 11
Ten = 10
def map_rank(rank_to_map):
if rank_to_map == 'A':
return Ace
if rank_to_map == 'K':
return King
if rank_to_map == 'Q':
return Queen
if rank_to_map == 'J':
return Jack
if rank_to_map == 'T':
return Ten
return int(rank_to_map)
def map_suit(suit_to_map):
if suit_to_map == 'H':
return 1
if suit_to_map == 'D':
return 2
if suit_to_map == 'C':
return 3
# S = Spades
return 4
def map_card(card_to_map):
return Card(rank=map_rank(card_to_map[0]), suit=map_suit(card_to_map[1]))
class Hand(object):
def __init__(self, *args):
self.cards = sorted(args, key=lambda c: -c.rank)
self.duplicates = {}
for card in self.cards:
if card.rank in self.duplicates:
continue
_duplicates = 0
for card2 in self.cards:
if card.rank == card2.rank:
_duplicates += 1
self.duplicates[card.rank] = _duplicates
def __cmp__(self, other):
for rule in self.rules():
rule = getattr(self, rule)
val = rule(other)
if val:
return val
def rules(self):
return []
def _straight(self):
last_card_rank = False
for card in self.cards:
if last_card_rank and last_card_rank != card.rank + 1:
return False
last_card_rank = card.rank
return True
def _flush(self):
last_card_suit = False
for card in self.cards:
if last_card_suit and last_card_suit != card.suit:
return False
last_card_suit = card.suit
return True
def _duplicate_count(self, c):
for rank, value in self.duplicates.items():
if value == c:
yield rank
class PokerHand(Hand):
def rules(self):
rules = super(PokerHand, self).rules()
rules.append('royal_flush')
rules.append('straight_flush')
rules.append('four_of_a_kind')
rules.append('full_house')
rules.append('flush')
rules.append('straight')
rules.append('three_of_a_kind')
rules.append('two_pair')
rules.append('highest_card')
return rules
def royal_flush(self, other):
h1 = self.cards[0].rank == Ace and self._flush() and self._straight()
h2 = other.cards[0].rank == Ace and other._flush() and other._straight()
if h1 and not h2:
return 1
if h2 and not h1:
return -1
if h1 and h2:
return 0
def straight_flush(self, other):
h1 = self._flush() and self._straight()
h2 = other._flush() and other._straight()
if h1 and not h2:
return 1
if h2 and not h1:
return -1
if h1 and h2:
return self.highest_card(other)
def four_of_a_kind(self, other):
return self._of_a_kind(other, 4)
def three_of_a_kind(self, other):
return self._of_a_kind(other, 3)
def _of_a_kind(self, other, value):
h1 = [r for r in self._duplicate_count(value)]
h2 = [r for r in other._duplicate_count(value)]
if len(h1) > len(h2):
return 1
if len(h2) > len(h1):
return -1
for h1_c, h2_c in zip(h1, h2):
if h1_c > h2_c:
return 1
if h2_c > h1_c:
return -1
def two_pair(self, other):
return self._of_a_kind(other, 2)
def full_house(self, other):
h1_3 = [r for r in self._duplicate_count(3)]
h2_3 = [r for r in other._duplicate_count(3)]
h1_2 = [r for r in self._duplicate_count(2)]
h2_2 = [r for r in other._duplicate_count(2)]
if h1_3 and h1_2 and not (h2_3 and h2_2):
return 1
if h2_3 and h2_2 and not (h1_3 and h1_2):
return -1
if h1_3 and h1_2 and h2_3 and h2_2:
for h1_c, h2_c in zip(h1_3, h2_3):
if h1_c > h2_c:
return 1
if h2_c > h1_c:
return -1
for h1_c, h2_c in zip(h1_2, h2_2):
if h1_c > h2_c:
return 1
if h2_c > h1_c:
return -1
def flush(self, other):
h1 = self._flush
h2 = other._flush
if h1 and not h2:
return 1
if h2 and not h1:
return -1
if h1 and h2:
return self.highest_card(other)
def straight(self, other):
h1 = self._straight
h2 = other._straight
if h1 and not h2:
return 1
if h2 and not h1:
return -1
if h1 and h2:
return self.highest_card(other)
def highest_card(self, other):
for c1,c2 in zip(self.cards, other.cards):
if c1.rank != c2.rank:
return 1 if c1.rank > c2.rank else -1
raise Exception("tie in highest_card")
def gen_hands(s):
cards = [map_card for c in s.split(' ')]
return PokerHand(*cards[0:5]), PokerHand(*cards[5:])
p1_wins = 0
with open('poker.txt') as f:
for line in f:
h1, h2 = gen_hands(line.strip())
if h1 > h2:
p1_wins += 1
print(p1_wins)
如果不添加 here 提供的 poker.txt 文件,程序将不会 运行 粘贴。如果在 SE 上为此类属性错误创建 post 是错误的,请告诉我。我不确定是否应该 post 在此站点上为 Project Euler 编写代码。
第 195 行,
cards = [map_card for c in s.split(' ')]
在
def gen_hands(s):
cards = [map_card for c in s.split(' ')]
return PokerHand(*cards[0:5]), PokerHand(*cards[5:])
生成一个列表,其中包含大量对 map_card
函数的引用。这被错误地写成 map_card
而不是 map_card(c)
。应该是
def gen_hands(s):
cards = [map_card(c) for c in s.split(' ')]
return PokerHand(*cards[0:5]), PokerHand(*cards[5:])
我正在通过自己编写代码和观看 Youtube videos.
来解决不同的 Project Euler 问题在处理问题 54 时,Youtube 视频的作者在 Python 2.7 中定义函数时编写的代码是
def __init__(self, *args):
self.cards = sorted(args, key=lambda c: -c.rank)
self.duplicates = {}
for card in self.cards:
if card.rank in self.duplicates:
continue
_duplicates = 0
for card2 in self.cards:
if card.rank == card2.rank:
_duplicates += 1
self.duplicates[card.rank] = _duplicates
这对他来说似乎很管用。当我在 Python 3.0 上 运行 这段代码时,我的 Pycharm 编译器 returns
File "C:/Users/Matthew/PycharmProjects/Project_Euler/Euler54.py", line 51, in __init__
self.cards = sorted(args, key=lambda c: -c.rank)
File "C:/Users/Matthew/PycharmProjects/Project_Euler/Euler54.py", line 51, in <lambda>
self.cards = sorted(args, key=lambda c: -c.rank)
AttributeError: 'function' object has no attribute 'rank'
我试过改变
self.cards = sorted(args, key=lambda c: -c.rank)
到
self.cards = sorted(args, key=lambda c: -c.rank())
但这似乎是一个不正确的修复。我不确定如何自行解决此错误。我可以考虑编写一个不同的解决方案,因为视频作者展示的策略对初学者来说并不友好。完整的程序粘贴在下面(我不确定是否应该包括这个,因为我没有正式寻找代码审查。我试图让程序达到 运行 以便我可以完成练习).
import time
from collections import namedtuple
start = time.time()
Card = namedtuple('Card', ['rank', 'suit'])
Ace = 14
King = 13
Queen = 12
Jack = 11
Ten = 10
def map_rank(rank_to_map):
if rank_to_map == 'A':
return Ace
if rank_to_map == 'K':
return King
if rank_to_map == 'Q':
return Queen
if rank_to_map == 'J':
return Jack
if rank_to_map == 'T':
return Ten
return int(rank_to_map)
def map_suit(suit_to_map):
if suit_to_map == 'H':
return 1
if suit_to_map == 'D':
return 2
if suit_to_map == 'C':
return 3
# S = Spades
return 4
def map_card(card_to_map):
return Card(rank=map_rank(card_to_map[0]), suit=map_suit(card_to_map[1]))
class Hand(object):
def __init__(self, *args):
self.cards = sorted(args, key=lambda c: -c.rank)
self.duplicates = {}
for card in self.cards:
if card.rank in self.duplicates:
continue
_duplicates = 0
for card2 in self.cards:
if card.rank == card2.rank:
_duplicates += 1
self.duplicates[card.rank] = _duplicates
def __cmp__(self, other):
for rule in self.rules():
rule = getattr(self, rule)
val = rule(other)
if val:
return val
def rules(self):
return []
def _straight(self):
last_card_rank = False
for card in self.cards:
if last_card_rank and last_card_rank != card.rank + 1:
return False
last_card_rank = card.rank
return True
def _flush(self):
last_card_suit = False
for card in self.cards:
if last_card_suit and last_card_suit != card.suit:
return False
last_card_suit = card.suit
return True
def _duplicate_count(self, c):
for rank, value in self.duplicates.items():
if value == c:
yield rank
class PokerHand(Hand):
def rules(self):
rules = super(PokerHand, self).rules()
rules.append('royal_flush')
rules.append('straight_flush')
rules.append('four_of_a_kind')
rules.append('full_house')
rules.append('flush')
rules.append('straight')
rules.append('three_of_a_kind')
rules.append('two_pair')
rules.append('highest_card')
return rules
def royal_flush(self, other):
h1 = self.cards[0].rank == Ace and self._flush() and self._straight()
h2 = other.cards[0].rank == Ace and other._flush() and other._straight()
if h1 and not h2:
return 1
if h2 and not h1:
return -1
if h1 and h2:
return 0
def straight_flush(self, other):
h1 = self._flush() and self._straight()
h2 = other._flush() and other._straight()
if h1 and not h2:
return 1
if h2 and not h1:
return -1
if h1 and h2:
return self.highest_card(other)
def four_of_a_kind(self, other):
return self._of_a_kind(other, 4)
def three_of_a_kind(self, other):
return self._of_a_kind(other, 3)
def _of_a_kind(self, other, value):
h1 = [r for r in self._duplicate_count(value)]
h2 = [r for r in other._duplicate_count(value)]
if len(h1) > len(h2):
return 1
if len(h2) > len(h1):
return -1
for h1_c, h2_c in zip(h1, h2):
if h1_c > h2_c:
return 1
if h2_c > h1_c:
return -1
def two_pair(self, other):
return self._of_a_kind(other, 2)
def full_house(self, other):
h1_3 = [r for r in self._duplicate_count(3)]
h2_3 = [r for r in other._duplicate_count(3)]
h1_2 = [r for r in self._duplicate_count(2)]
h2_2 = [r for r in other._duplicate_count(2)]
if h1_3 and h1_2 and not (h2_3 and h2_2):
return 1
if h2_3 and h2_2 and not (h1_3 and h1_2):
return -1
if h1_3 and h1_2 and h2_3 and h2_2:
for h1_c, h2_c in zip(h1_3, h2_3):
if h1_c > h2_c:
return 1
if h2_c > h1_c:
return -1
for h1_c, h2_c in zip(h1_2, h2_2):
if h1_c > h2_c:
return 1
if h2_c > h1_c:
return -1
def flush(self, other):
h1 = self._flush
h2 = other._flush
if h1 and not h2:
return 1
if h2 and not h1:
return -1
if h1 and h2:
return self.highest_card(other)
def straight(self, other):
h1 = self._straight
h2 = other._straight
if h1 and not h2:
return 1
if h2 and not h1:
return -1
if h1 and h2:
return self.highest_card(other)
def highest_card(self, other):
for c1,c2 in zip(self.cards, other.cards):
if c1.rank != c2.rank:
return 1 if c1.rank > c2.rank else -1
raise Exception("tie in highest_card")
def gen_hands(s):
cards = [map_card for c in s.split(' ')]
return PokerHand(*cards[0:5]), PokerHand(*cards[5:])
p1_wins = 0
with open('poker.txt') as f:
for line in f:
h1, h2 = gen_hands(line.strip())
if h1 > h2:
p1_wins += 1
print(p1_wins)
如果不添加 here 提供的 poker.txt 文件,程序将不会 运行 粘贴。如果在 SE 上为此类属性错误创建 post 是错误的,请告诉我。我不确定是否应该 post 在此站点上为 Project Euler 编写代码。
第 195 行,
cards = [map_card for c in s.split(' ')]
在
def gen_hands(s):
cards = [map_card for c in s.split(' ')]
return PokerHand(*cards[0:5]), PokerHand(*cards[5:])
生成一个列表,其中包含大量对 map_card
函数的引用。这被错误地写成 map_card
而不是 map_card(c)
。应该是
def gen_hands(s):
cards = [map_card(c) for c in s.split(' ')]
return PokerHand(*cards[0:5]), PokerHand(*cards[5:])