星号和f'{}'到底怎么用?

如题,要求生成一个八行十列的列表,列表内数字在0-10之间。
代码1:
from random import choices
m,n=8,10
i=[choices(range(10),k=n)for _ in range(m)]
print(*i,sep='\n')
运行结果:
[3, 1, 4, 2, 5, 2, 7, 6, 9, 5]
[1, 9, 8, 2, 3, 2, 4, 7, 6, 9]
[9, 7, 3, 3, 7, 5, 5, 8, 2, 9]
[3, 7, 3, 2, 4, 8, 1, 9, 8, 1]
[5, 8, 6, 6, 7, 1, 4, 0, 9, 7]
[6, 0, 2, 0, 5, 6, 9, 2, 2, 3]
[2, 3, 3, 2, 2, 4, 2, 6, 4, 2]
[8, 1, 4, 3, 4, 5, 5, 5, 3, 3]
代码2:from random import choices
m,n=8,10
i=[choices(range(10),k=n)for _ in range(m)]
print(f'{i}',sep='\n')
运行结果:[[4, 3, 0, 3, 9, 9, 9, 1, 6, 4], [7, 8, 6, 9, 8, 4, 8, 1, 9, 6], [3, 6, 9, 9, 7, 8, 7, 2, 4, 5], [6, 1, 2, 1, 4, 6, 4, 1, 0, 5], [0, 0, 2, 6, 7, 0, 2, 7, 5, 0], [8, 4, 4, 7, 4, 8, 1, 6, 3, 5], [9, 0, 0, 6, 3, 1, 4, 0, 1, 8], [3, 3, 2, 2, 1, 0, 9, 0, 6, 7]]
如果直接print(i,sep='\n'),结果与代码2一样,f'{}'和星号到底怎么用,什么情况下要用到这两个?

f'{}'是字符串的格式化
str.format() 比 %格式化高级了一些,但是它还是有自己的缺陷。当需要传入的字符串过多时,仍然会显得非常冗长。与在Python 3.6中引入 了f-strings,不仅比str.format更简洁,性能上也更胜一筹
​ f-string是以f或F开头的字符串, 核心在于字符串中符号{}的使用
{}中可以是变量名

name = 'egon'
age = 18
print(f'{name} {age}')  # egon 18
print(F'{age} {name}')  # 18 egon

{}中可以是表达式


# 可以在{}中放置任意合法的Python表达式,会在运行时计算
# 比如:数学表达式
print(f'{3*3/2}') # 4.5

# 比如:函数的调用
def foo(n):
    print('foo say hello')
    return n

print(f'{foo(10)}') # 会调用foo(10),然后打印其返回值

# 比如:调用对象的方法
name='EGON'
print(f'{name.lower()}') # egon

有帮助的话采纳一下哦!