Python程序笔记2023002
Alice、Bob 和他们的朋友们
问题主体
密码学家 Rivest、Shamir、Adleman 于1977年4月撰写了一篇论文《数字签名与公钥密码学》(On Digital Signatures and Public-Key Cryptosystems),并投稿至了一个期刊上,不过很遗憾这篇论文被拒稿了。随后他们修改了论文,并将论文重新命名为《一种实现数字签名和公钥密码系统的方法》(A Method of Obtaining Digital Signatures and Public-Key Cryptosystems),最终于1978年2月成功发表于顶级期刊《ACM 通信》(Communications of the ACM)。在这篇论文中,三位密码学家嫌弃使用 A、B 两个字母代表角色太无聊,就用 Alice 和 Bob 来代替 A 和 B。
在随后的几十年里密码学界又新增了很多著名人物。布鲁斯·施奈尔所著的《应用密码学》(Applied Cryptography)里详细列举了这些人物,下面是一些例子:
crypto_roles = [
'爱丽丝(Alice)是信息发送者。',
'与鲍伯(Bob)是信息接受者。通例上,爱丽丝希望把一条消息发送给鲍伯。',
'卡罗尔或查利(Carol或Charlie)是通信中的第三位参加者。',
'戴夫(Dave)是通信中的第四位参加者。',
'伊夫(Eve)是一位偷听者(eavesdropper),但行为通常是被动的。她拥有偷听的技术,但不会中途篡改发送的消息。在量子密码学中,伊夫也可以指环境(environment)。'
]
Python 是一门多范式编程语言,其中包括面向对象编程。
首先,我们用 Python 类(class)
定义一个密码城邦人物类型:
class CryptographyPeople:
def __init__(self, name_cn, name_en, role, desc):
self.name_cn = name_cn
self.name_en = name_en
self.role = role
self.desc = desc
其次,我们添加一个简易的密码城邦人物解析器,它的作用是将类似'马提尔达(Matilda)是一位商人(merchant),用于电子商务。',
这样的人物剧本
解析成CryptographyPeople
,创建一个密码城邦人物:
class SimpleCryptographyPeopleParser:
def __init__(self, text) -> None:
self.text = text
def parse(self, desc):
# 解析名字部分
name_cn, name_en, rest = self.parse_name(desc)
# 解析角色部分
role, rest = self.parse_role(rest)
# 解析描述不符
desc = self.parse_desc(rest)
# 创建密码城邦人物
people = CryptographyPeople(name_cn, name_en, role, desc)
return people
def parse_name(self, text):
# 解析名字部分
index = text.find('是')
name, rest = text[0:index], text[index+1:]
# 解析中英文名字
start = name.find('(')
end = name.find(')')
name_cn = name[0:start]
name_en = name[start+1:end]
return name_cn.strip(), name_en.strip(), rest
def parse_role(self, text):
index1 = text.find('。')
index2 = text.find(',')
index = 0
if index1 > 0 and index2 > 0:
index = min(index1, index2)
else:
index = max(index1, index2)
role, rest = text[0:index], text[index+1:len(text)-1]
# 去除冗余量词
counts = ['一名', '一位', '一个']
for count in counts:
role = role.replace(count, '')
return role.strip(), rest.strip()
def parse_desc(self, name_cn, name_en, role, rest):
desc = rest
if desc:
# 识别自我主语
self_list = [name_cn, '他', '她']
for self_item in self_list:
desc = desc.replace(self_item, '我')
else:
# 补充默认描述
desc = '很高兴认识你'
最后,我们希望创建一个密码城邦,它包含 add
和 introduce
两个方法:
class CryptographyCity:
def __init__(self):
self.peoples = []
def add(self, text):
parser = SimpleCryptographyPeopleParser(text)
people = parser.parse(text)
self.peoples.append(people)
# TODO(YOU): 请在此实现 introduce 方法
最终,我们可以构建起密码城邦,并让市民们全部自报家门:
if __name__ == '__main__':
crypto_roles = ...
city = CryptographyCity()
for crypto_role in crypto_roles:
city.add(crypto_role)
city.introduce()
密码城邦人物的自我介绍如下:
爱丽丝(Alice): 密码学家说我是一位信息发送者,很高兴认识你。
鲍伯(Bob): 密码学家说我是一位信息接受者,通例上,爱丽丝希望把一条消息发送给我。
...
结构分析 1
def __init__(self, name_cn, name_en, role, desc):
def __init__
是 Python 中的一个特殊方法,也称为类的构造函数。它是在创建一个新的类实例时被自动调用的方法,用于初始化实例的属性。
init 的作用
__init__
的作用有两种,一种是用于定义类的构造函数,另一种是用于标识一个目录是一个 python 的模块包。
第一种作用,就是在创建类的对象时初始化对象的属性或执行一些其他操作。
第二种作用,是当一个目录中包含了 __init__.py
文件时,这个目录就会被认为是一个 python 的模块包,可以被 import 导入。
魔法函数
在 python 中,有一些方法或变量的名字是以双下划线“__
”开头和结尾的,它们是 python 的魔法函数或魔法变量,有一些特殊的含义或功能。前后都加上“__
”,是为了区别它和普通的方法或变量,表示它是一个魔法函数,不是用户自定义的函数。这样可以避免命名冲突,也可以让 python 解释器识别它并执行相应的操作。
双下划线开头和结尾的魔法函数是 Python 的内置函数,一般以__xx__的形式命名,每个魔法函数对应一个内置函数或者运算符,比如 __init__
对应构造函数,__str__
对应 str ()函数,__add__
对应+运算符等。
双下划线开头和结尾的魔法函数是 Python 的一种高级语法,允许你在类中自定义函数,并绑定到类的特殊方法中,从而为类提供一些额外的功能或特性,比如运算符重载、迭代器、上下文管理器等。
双下划线开头和结尾的魔法函数是 Python 社区一致认可的命名约定,用来区分普通的方法和特殊的方法,避免与用户自定义的方法名冲突。
常用的魔法函数有以下几种:
__str__(self)
:返回对象的字符串表示,通常用于将对象转换为人类可读的字符串格式。__repr__(self)
:返回对象的字符串表示,通常用于将对象转换为程序可读的字符串格式。__len__(self)
:返回对象的长度,通常用于计算容器对象中元素的个数。__getitem__(self, key)
:根据给定的键获取对象中的值,通常用于实现索引操作,支持通过索引或切片访问容器对象中的元素。__setitem__(self, key, value)
:根据给定的键设置对象中的值,通常用于实现赋值操作,支持通过索引或切片修改容器对象中的元素。__call__(self, *args, **kwargs)
:将对象作为函数调用,通常用于实现可调用对象,使得对象可以像函数一样被调用。__eq__(self, other)
:比较两个对象是否相等,通常用于实现对象的比较操作。__lt__(self, other)
:比较两个对象的大小关系,通常用于实现对象的排序操作。__add__(self, other)
:将两个对象相加,通常用于实现对象的加法操作。__sub__(self, other)
:将两个对象相减,通常用于实现对象的减法操作。
如果您想判断一个对象是否实现了某个魔法函数,您可以使用以下的方法:
- 使用 hasattr ()函数,传入对象和魔法函数的名称(字符串形式),如果返回 True,表示对象实现了该魔法函数,否则表示没有实现。例如,
hasattr(obj, “__str__”)
可以判断 obj 是否实现了__str__方法。 - 使用 callable ()函数,传入对象和魔法函数的名称(属性形式),如果返回 True,表示对象实现了该魔法函数,否则表示没有实现。例如,
callable(obj.__str__)
可以判断 obj 是否实现了__str__方法。 - 使用 try-except 语句,尝试调用对象和魔法函数的名称(属性形式),如果没有抛出异常,表示对象实现了该魔法函数,否则表示没有实现。例如,
try: obj.__str__() except: print(“obj没有实现__str__方法”)
可以判断 obj 是否实现了__str__方法。
下面是一个简单的例子,判断一个列表对象是否实现了以下几个魔法函数:
lst = [1, 2, 3]
# 使用hasattr()函数
print(hasattr(lst, "__len__")) # True
print(hasattr(lst, "__add__")) # True
print(hasattr(lst, "__call__")) # False
# 使用callable()函数
print(callable(lst.__len__)) # True
print(callable(lst.__add__)) # True
print(callable(lst.__call__)) # False
# 使用try-except语句
try:
lst.__len__()
except:
print("lst没有实现__len__方法")
else:
print("lst实现了__len__方法")
try:
lst.__add__(lst)
except:
print("lst没有实现__add__方法")
else:
print("lst实现了__add__方法")
try:
lst.__call__()
except:
print("lst没有实现__call__方法")
else:
print("lst实现了__call__方法")
结构分析 2
def parse_role(self, text):
index1 = text.find('。')
index2 = text.find(',')
index = 0
if index1 > 0 and index2 > 0:
index = min(index1, index2)
else:
index = max(index1, index2)
role, rest = text[0:index], text[index+1:len(text)-1]
# 去除冗余量词
counts = ['一名', '一位', '一个']
for count in counts:
role = role.replace(count, '')
return role.strip(), rest.strip()
当解析角色部分时,parse_role
方法接收一个字符串参数 text
,该字符串代表密码城邦人物的角色信息。该方法首先使用 find
方法查找字符串中第一个出现句号 。
和逗号 ,
的位置,并根据它们的位置来截取字符串。这个位置的索引就是字符串 index
的值。如果在字符串中没有找到句号或逗号,index
将为0,表示没有角色信息。
然后,该方法从text
字符串中截取角色字符串role
和剩余信息字符串rest
。在剩余信息中,从字符串开头和结尾中删除role
字符串的字符,以获得纯粹的剩余信息。
最后,该方法通过遍历预定义的冗余量词列表 counts
,使用 replace
方法删除角色字符串中的冗余量词。最后返回清理后的角色字符串 role
和剩余信息字符串 rest
。
def parse_desc(self, name_cn, name_en, role, rest):
desc = rest
if desc:
# 识别自我主语
self_list = [name_cn, '他', '她']
for self_item in self_list:
desc = desc.replace(self_item, '我')
else:
# 补充默认描述
desc = '很高兴认识你'
这段代码是 SimpleCryptographyPeopleParser
类中的 parse_desc
方法,用于解析人物的描述部分。
方法接受四个参数,分别是人物的中文名字、英文名字、角色和剩余的未解析部分。方法首先将未解析部分作为描述赋值给变量 desc
,然后判断 desc
是否为空。如果不为空,即有描述部分,就会进行自我主语的识别和替换。
这里定义了一个 self_list
列表,包含了人物的中文名字、"他" 和 "她" 三种可能的自我主语。接下来使用 replace
函数将其中的每个元素都替换成 "我",以使描述符合第一人称视角的要求。如果 desc
为空,则将描述赋值为 "很高兴认识你",作为默认描述。最后返回处理后的描述。
补全代码
前半部分
class CryptographyCity:
def __init__(self):
self.peoples = []
def add(self, text):
parser = SimpleCryptographyPeopleParser(text)
people = parser.parse(text)
self.peoples.append(people)
这段代码定义了一个名为 CryptographyCity 的类,这个类表示一个密码城邦,拥有一个属性 peoples
,代表该城邦的人物角色列表。
这个类还定义了一个方法add
,用于向城邦中添加新的人物角色。该方法接受一个字符串参数text
,并使用SimpleCryptographyPeopleParser
类的实例parser
来解析这个字符串。parser
实例将字符串解析为一个CryptographyPeople
对象,表示一个密码城邦的人物角色,然后将这个对象添加到城邦的peoples
列表中。
中间部分
def introduce(self):
for people in self.peoples:
self.say(people)
def introduce(self):
for people in peoples:
say(people)
def introduce(self):
i = 0
while i < len(self.peoples):
people = self.peoples[i]
self.say(people)
i += 1
def introduce(self):
[self.say(people) for people in self.peoples]
后面部分
def say(self, people):
info = f'{people.name_cn}({people.name_en}): 密码学家说我是一位{people.role},{people.desc}。'
print(info)
整体代码优化
# @Time:2022/12/14 0014 16:12
# @Author:晚秋拾叶
# @File:AliceBob.py
# @PyCharm之Python
# 定义一个密码城邦人物类型
class CryptographyPeople:
def __init__(self, name_cn, name_en, role, desc):
self.name_cn = name_cn
self.name_en = name_en
self.role = role
self.desc = desc
# 简易密码城邦人物解析器,它的作用是将类似'马提尔达(Matilda)是一位商人(merchant),用于电子商务。',
# 这样的人物剧本解析成CryptographyPeople,创建一个密码城邦人物
# 单个人物的解析
class SimpleCryptographyPeopleParser:
def __init__(self, text) -> None:
self.text = text
# 1.名字解析,包括中文和英文两部分,并返回
def parse_name(self, text):
# 解析名字部分,析出name和rest
index = text.find('是')
name = text[0:index]
# 解析中英文名字
start = name.find('(')
end = name.find(')')
name_cn = name[0:start].strip()
name_en = name[start + 1:end].strip()
# 返回中文、英文名字和剩余文字
return name_cn, name_en
# 2. 解析密码城邦人物的角色部分
def parse_role(self, text):
index_is = text.find('是')
index1 = text.find('。')
index2 = text.find(',')
if index1 and index2:
index = min(index1, index2)
else:
index = max(index1, index2)
role = text[index_is:index]
# 去除冗余量词
counts = ['一名', '一位', '一个']
for count in counts:
role = role.replace(count, '').strip()
return role
# 3.对剩余部分的解析,进行优化处理,本人名字换为第一人称,如果没有剩余部分,再加上问候语。
def parse_desc(self, text):
index1 = text.find('。')
index2 = text.find(',')
if index1 and index2:
index = min(index1, index2)
else:
index = max(index1, index2)
rest = text[index + 1:]
name_cn = self.parse_name(text)[0]
if index > 0:
# 识别自我主语
self_list = [name_cn, '她']
for self_item in self_list:
rest = rest.replace(self_item, '我')
else:
# 补充默认描述
rest = '很高兴认识你。'
return rest
# 总的解析,完成并返回一个清晰的人物
def parse(self, text):
# 把解析出来的中英文名字部分和剩余部分,分别放到两个对应的变量
name_cn, name_en = self.parse_name(text)
# 解析剩余部分,得到角色部分
role = self.parse_role(text)
# 解析不够长的描述部分
desc1 = self.parse_desc(self.text)
# 创建密码城邦人物介绍,内容包括中文名字,英文名字,人物角色,人物描述
people = CryptographyPeople(name_cn, name_en, role, desc1)
return people
# 说出密码城堡里的人物信息
class CryptographyCity:
def __init__(self):
self.peoples = []
# 把短文中的每个人物简介,解析成“中文名+英文名+描述”,然后放入列表peoples中
def add(self, text):
parser = SimpleCryptographyPeopleParser(text)
people = parser.parse(text)
self.peoples.append(people)
# 再调用say()方法,把peoples中的内容,更新组织起来,输出。
def introduce(self):
i = 0
while i < len(self.peoples):
people = self.peoples[i]
self.say(people)
i += 1
def say(self, people):
info = f'{people.name_cn}({people.name_en}): 密码学家说我是一位{people.role},{people.desc}'
print(info)
if __name__ == '__main__':
crypto_roles = [
'爱丽丝(Alice)是信息发送者。',
'鲍伯(Bob)是信息接受者。通例上,爱丽丝希望把一条消息发送给鲍伯。',
'卡罗尔或查利(Carol或Charlie)是通信中的第三位参加者。',
'戴夫(Dave)是通信中的第四位参加者。',
'伊夫(Eve)是一位偷听者(eavesdropper),但行为通常是被动的。她拥有偷听的技术,但不会中途篡改发送的消息。'
'在量子密码学中,伊夫也可以指环境(environment)。'
]
city = CryptographyCity()
for crypto_role in crypto_roles:
city.add(crypto_role)
city.introduce()
输出结果
爱丽丝 (Alice): 密码学家说我是一位是信息发送者,很高兴认识你。
鲍伯 (Bob): 密码学家说我是一位是信息接受者,通例上,爱丽丝希望把一条消息发送给我。
卡罗尔或查利 (Carol 或 Charlie): 密码学家说我是一位是通信中的第三位参加者,很高兴认识你。
戴夫 (Dave): 密码学家说我是一位是通信中的第四位参加者,很高兴认识你。
伊夫 (Eve): 密码学家说我是一位是偷听者(eavesdropper),但行为通常是被动的。我拥有偷听的技术,但不会中途篡改发送的消息。在量子密码学中,我也可以指环境(environment)。
编写一个二维向量类 Vector
一个简单的例子,实现了一个二维向量类 Vector,它支持加减、乘除、长度、字符串表示和迭代
class Vector(object):
# 构造函数
def __init__(self, x, y):
self.x = x
self.y = y
# 字符串表示
def __str__(self):
return "({},{})".format(self.x, self.y)
# 加法运算
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
# 减法运算
def __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y)
# 长度
def __len__(self):
return 2
# 迭代器
def __iter__(self):
self.index = 0
return self
# 迭代元素
def __next__(self):
if self.index < len(self):
value = (self.x, self.y)[self.index]
self.index += 1
return value
else:
raise StopIteration
# 乘法运算
def __mul__(self, other):
# 如果另一个对象也是向量,则进行点乘
if isinstance(other, Vector):
return self.x * other.x + self.y * other.y
# 如果另一个对象是数字,则进行标量乘法
elif isinstance(other, (int, float)):
return Vector(self.x * other, self.y * other)
# 否则抛出异常
else:
raise TypeError("Unsupported operand type(s) for *: 'Vector' and '{}'".format(type(other)))
# 测试代码
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2)
print(v1 - v2)
print(v1 * v2) # 11
print(v1 * 2) # (2,4)
print(v1 * "a") # TypeError: Unsupported operand type(s) for *: 'Vector' and '<class 'str'>'
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"({self.x}, {self.y})"
def __repr__(self):
return f"Vector({self.x}, {self.y})"
def __len__(self):
return 2
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y)
def __mul__(self, other):
if isinstance(other, (int, float)):
return Vector(self.x * other, self.y * other)
elif isinstance(other, Vector):
return Vector(self.x * other.x, self.y * other.y)
else:
raise TypeError(f"unsupported operand type(s) for *: '{type(self).__name__}' and '{type(other).__name__}'")
def __rmul__(self, other):
return self.__mul__(other)
def __truediv__(self, other):
if isinstance(other, (int, float)):
return Vector(self.x / other, self.y / other)
elif isinstance(other, Vector):
return Vector(self.x / other.x, self.y / other.y)
else:
raise TypeError(f"unsupported operand type(s) for /: '{type(self).__name__}' and '{type(other).__name__}'")
def __iter__(self):
self.current = 0
return self
def __next__(self):
if self.current >= 2:
raise StopIteration
if self.current == 0:
result = self.x
else:
result = self.y
self.current += 1
return result
def length(self):
return (self.x ** 2 + self.y ** 2) ** 0.5
v1 = Vector(1, 2)
v2 = Vector(3, 4)
v3 = Vector(5, 6)
# 测试加法运算
print(v1 + v2) # 输出 (4, 6)
print(v1 + v2 + v3) # 输出 (9, 12)
# 测试减法运算
print(v1 - v2) # 输出 (-2, -2)
print(v1 - v2 - v3) # 输出 (-7, -8)
# 测试长度函数
print(abs(v1)) # 输出 2.23606797749979
print(abs(v2)) # 输出 5.0
# 测试字符串表示
print(str(v1)) # 输出 "<1, 2>"
print(str(v2)) # 输出 "<3, 4>"
# 测试迭代器
for i in v1:
print(i) # 输出 1 和 2
# 测试乘法运算
print(v1 * 2) # 输出 <2, 4>
print(2 * v1) # 输出 <2, 4>
# 测试除法运算
print(v1 / 2) # 输出 <0.5, 1.0>
编写一个类练习 self
如果想自己写一个类来练习一下 self,可以参考以下的步骤:
- 首先,需要确定您想要写的类的名称、属性和方法,以及它们的作用和功能。
- 然后,需要在类的定义中使用class关键字,以及括号中的object或其他基类(如果有的话)。
- 接着,需要在类中定义一个__init__方法,用来初始化类的实例属性。在
__init__
方法中,需要使用self参数来表示类的实例,并用self.属性名 = 参数名
的形式来赋值。 - 然后,需要在类中定义其他的实例方法,用来实现类的行为。在实例方法中,也需要使用self参数来表示类的实例,并用
self.属性名
或self.方法名
的形式来访问或调用。 - 最后,您需要创建类的实例对象,并调用它们的属性和方法,看看是否符合您的预期。
下面是一个简单的例子,写一个表示学生的类 Student,它有姓名、年龄和成绩三个属性,以及一个打印信息的方法:
# 定义Student类
class Student(object):
# 定义__init__方法
def __init__(self, name, age, score):
# 使用self参数来初始化实例属性
self.name = name
self.age = age
self.score = score
# 定义print_info方法
def print_info(self):
# 使用self参数来访问实例属性
print(f"姓名:{self.name},年龄:{self.age},成绩:{self.score}")
# 创建Student类的实例对象
s1 = Student("张三", 18, 90)
s2 = Student("李四", 19, 80)
# 调用实例对象的属性和方法
s1.print_info()
s2.print_info()
class Student:
def __init__(self, name, age, grade):
self.name = name
self.age = age
self.grade = grade
self.classes = []
def __str__(self):
return f"{self.name} ({self.age} years old, {self.grade} grade)"
def __repr__(self):
return f"Student('{self.name}', {self.age}, {self.grade})"
def __len__(self):
return len(self.classes)
def __getitem__(self, index):
return self.classes[index]
def __setitem__(self, index, value):
self.classes[index] = value
def __add__(self, other):
name = f"{self.name} and {other.name}"
age = max(self.age, other.age)
grade = min(self.grade, other.grade)
new_student = Student(name, age, grade)
new_student.classes = self.classes + other.classes
return new_student
def add_class(self, class_name):
self.classes.append(class_name)
这个示例定义了一个 Student
类,每个学生都有一个名字、年龄和年级,还可以选择加入多个课程。这个类包括了 __init__
、__str__
、__repr__
、__len__
、__getitem__
、__setitem__
、__add__
等常用的魔法函数,它们分别用于初始化对象、返回对象的字符串表示、返回对象的程序可读表示、返回对象的长度、支持索引和切片访问容器对象中的元素、支持通过索引或切片修改容器对象中的元素、将两个对象相加等操作。
编写一个类练习静态方法和类方法
写一个类来练习一下静态方法和类方法,您可以参考以下的步骤:
- 首先,需要确定想要写的类的名称、属性和方法,以及它们的作用和功能。
- 然后,需要在类的定义中使用class关键字,以及括号中的object或其他基类(如果有的话)。
- 接着,需要在类中定义一个__init__方法,用来初始化类的实例属性。在__init__方法中,需要使用self参数来表示类的实例,并用
self.属性名 = 参数名
的形式来赋值。 - 然后,需要在类中定义一个或多个静态方法,用来实现一些与实例或类无关的功能。在静态方法中,不需要使用self或cls参数,只需使用@staticmethod装饰器来修饰。
- 然后,需要在类中定义一个或多个类方法,用来实现一些与类相关的功能。在类方法中,需要使用cls参数来表示类本身,并用@classmethod装饰器来修饰。
- 最后,需要创建类的实例对象,并调用它们的属性和方法,看看是否符合您的预期。
下面是一个简单的例子,写一个表示矩形的类 Rectangle,它有长和宽两个属性,以及一个计算面积的实例方法、一个计算周长的静态方法和一个根据面积创建矩形对象的类方法:
# 定义Rectangle类
class Rectangle(object):
# 定义__init__方法
def __init__(self, length, width):
# 使用self参数来初始化实例属性
self.length = length
self.width = width
# 定义area实例方法
def area(self):
# 使用self参数来访问实例属性
return self.length * self.width
# 定义perimeter静态方法
@staticmethod
def perimeter(length, width):
# 不需要使用self或cls参数
return (length + width) * 2
# 定义create类方法
@classmethod
def create(cls, area):
# 使用cls参数来表示类本身
length = area ** 0.5
width = length
return cls(length, width)
# 创建Rectangle类的实例对象
r1 = Rectangle(3, 4)
r2 = Rectangle.create(16)
# 调用实例对象的属性和方法
print(r1.length, r1.width)
print(r1.area())
print(r2.length, r2.width)
print(r2.area())
# 调用静态方法和类方法
print(Rectangle.perimeter(3, 4))
print(Rectangle.create(25).area())