(python)代码学习||2024.2.3||题目是codewars上的【Validate Sudoku with size `NxN`】
题目的要求是写一个Sudoku类,类中要有一个实例函数判断传给对象的二维数组是否符合数独规则
题目链接:https://www.codewars.com/kata/540afbe2dc9f615d5e000425/python
下面是写完题后看到的别人的解决方法
from itertools import chain class Sudoku(object): def __init__(self, grid): self.grid = grid self.size = len(grid) self.good_zone = set(range(1, self.size + 1)) def __iter__(self): """Iterate over each row, column and square of the sudoku""" rows = self.grid cols = zip(*rows) square_size = int(self.size ** 0.5) squares = [sum((rows[y+i][x:x+square_size] for i in range(square_size)), []) for y in range(0, self.size, square_size) for x in range(0, self.size, square_size)] return chain(rows, cols, squares) def valid_data_types(self): """Check data types""" return all(type(num) == int for num in chain(*self.grid)) def zone_is_valid(self, zone): """Check if a zone contain every numbers""" return set(zone) == self.good_zone def is_valid(self): """Is the sudoku solved""" if not self.valid_data_types(): return False return all(self.zone_is_valid(zone) for zone in self)
观察到的东西
- 函数
__iter__
返回值处的chain()
函数来自于from itertools import chain
,网上搜来的结果是这样的:Python中的chain()函数可以将多个迭代器组合起来,形成一个更大的迭代器。chain()函数的语法如下:itertools.chain(*iterables)
其中,*iterables
是一个可变参数,代表着可以传入多个可迭代的对象,如序列、列表、生成器等。chain()函数将这些可迭代对象连接起来成为一个更大的迭代器。大概用法应该是这样:
from itertools import chain a=[1,2,3] b=[4,5] c=('*','*') d = chain(a,b,c) print(d) for i in d: print(i,end=' ') #1 2 3 4 5 * * '''输出 <itertools.chain object at 0x00000210F2869E40> 1 2 3 4 5 * * '''
迭代器没学过,不过应该是一个可以遍历的东西
chain(rows,cols,squares)
中rows,cols,squares都是二级列表,所以函数返回的是一个更迭代器,其中的元素是他们三个二级列表的所有元素,即一些一级列表
- 函数
def valid_data_types(self)
最后的all(type(num) == int for num in chain(*self.grid))
处的chain(*self.grid)
。self.grid
是个二级列表,那这里chain处理之后的结果应该是一些元素(即num)为一级列表的迭代器,但是前面判断元素类型却是type(num)==int
。实际上chain(*self.grid)
的作用是将列表self.grid中的一级列表们中的所有元素放到一个迭代器中。这里应该是*在起作用:
a=[[1,2],[3,4]] print(*a) '''输出 [1, 2] [3, 4] '''
*
将二级列表中的一级列表们取出来,变成多个一级列表,于是chain就能对它们操作了
- 在函数is_valid最后的
for zone in self
处的self
实际上是__iter__
的返回值chain(rows, cols, squares)
,实验了一下:
from itertools import chain class test(object): def __iter__(self): return chain([1,2,3]) aa=test() print(aa) print(list(aa)) for i in aa: print(i,end=' ') ''' <__main__.test object at 0x0000026A1442A0C0> [1, 2, 3] 1 2 3 '''
这里如果把def __iter__(self)
中的self
去掉会在print(list(aa))
处报错,报错为:
TypeError: test.iter() takes 0 positional arguments but 1 was given
如果把return chain([1,2,3])
该为return [1,2,3]
会在print(list(aa))
处报错:
TypeError: iter() returned non-iterator of type 'list'
网上搜出来的东西也没看懂多少,似乎__iter__
正常的用法类似于这样:
class test(): def __init__(self,end): self.end=end def __iter__(self): print('__iter__被调用了') self.a=-1 return self def __next__(self): print('__next__被调用了') self.a+=1 if self.a>self.end: raise StopIteration() return self.a for i in test(5): print(i) '''换成这样是一样的输出 a=test(5) for i in a: print(i) ''' '''输出 __iter__被调用了 __next__被调用了 0 __next__被调用了 1 __next__被调用了 2 __next__被调用了 3 __next__被调用了 4 __next__被调用了 5 __next__被调用了 '''
看起来是要遍历test类的对象时会自动调用__iter__
函数,每次遍历(包括第一次遍历以及结束时的那个没有遍历出结果的遍历)都会调用__next__
函数,遍历出来的东西就是__next__
的返回值
- 函数
is_valid(self)
和函数valid_data_types(self)
最后的返回处都出现了all()函数,以下来自菜鸟教程:
all()
函数用于判断给定的可迭代参数 iterable
中的所有元素是否都为 TRUE
,如果是返回 True
,否则返回 False
元素除了是 0、空、None、False 外都算 True。
函数等价于:
def all(iterable): for element in iterable: if not element: return False return True
使用例子:
print(all([1,1,1])) print(all([1,1,0])) '''输出 True False ''' print(all([True,True,True])) print(all([True,True,False])) '''输出 True False '''
- 函数
__iter__(self)
中生成squares
的部分
squares = [sum( (rows[y+i][x:x+square_size] for i in range(square_size)), [] ) for y in range(0, self.size, square_size) for x in range(0, self.size, square_size)]
进行了下面的测试:
a_tup=(1,2,3) a=([1],[2],[3]) b=[4,5,6] c=sum(a,b) #c=sum(a_tup,b)#TypeError: can only concatenate list (not "int") to list print(c)#[4, 5, 6, 1, 2, 3] d=sum(b) print(d)#15 e=sum((1,2),3) print(e)#6
如果(rows[y+i][x:x+square_size] for i in range(square_size))
这部分生成式最外面的括号如果是中括号的话,那这就会变成一个二级列表了,(原来是一个元素为列表的元组),这样经过sum运算就会变成一个元素既有一级列表也有数字的列表了,这里本来是想生成一个元素只有数字的一级列表的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现