16. 第十六章 类和函数

16. 类和函数

现在我们已经知道如何创建新的类型,
下一步是编写接收用户定义的对象作为参数或者将其当作结果用户定义的函数.
本章我会展示'函数式编程风格', 以及两个新的程序开发计划.
本章的代码示例可以从↓下载.
https://github.com/AllenDowney/ThinkPython2/blob/master/code/Time1.py
练习的解答在↓.
https://github.com/AllenDowney/ThinkPython2/blob/master/code/Time1_soln.py
16.1 时间
作为用户定义类型的另一个例子, 我们定义一个叫Time的的类, 用于记录一天里的时间. 类定义如下:
class Time:
	"""Represents the time of day.
	attributes: hour, minute, second
	"""
	
我们可以创建一个Time对象并给其属性小时数, 分钟数和秒钟数赋值:
time = Time()
time.hour = 11
time.minute = 59
time.second = 30

Time对象的状态图参见图16-1.

2023-04-17_00001

作为练习, 编写一个叫作print_time的函数, 接收一个Time对象作为形参
并以'hour:minute:second'的格式打印它.
提示: 格式序列'%.2d'可以以最少两个字符打印一个整数, 如果需要, 它会在前面添加前缀0.
class Time:
    """Represents the time of day.
    attributes: hour, minute, second
    """


def print_time(time_obj):
    print('%.2d:%.2d:%.2d' % (time_obj.hour, time_obj.minute, time_obj.second))


def main():
    time = Time()
    time.hour = 11
    time.minute = 59
    time.second = 30

    print_time(time)


if __name__ == '__main__':
    main()

编写一个布尔函数is_after, 接收两个Time对象, t1和t2, 
并若t1在t2时间之后, 则返回True, 否则返回False. 
挑战不许使用if表达式.
class Time:
    """Represents the time of day.
    attributes: hour, minute, second
    """


def print_time(time_obj):
    print('%.2d:%.2d:%.2d' % (time_obj.hour, time_obj.minute, time_obj.second))


def main():
    time = Time()
    time.hour = 11
    time.minute = 59
    time.second = 30

    print_time(time)

    time2 = Time()
    time2.hour = 11
    time2.minute = 59
    time2.second = 32
    res = is_after(time, time2)
    print(res)


def is_after(t1, t2):
    # t1的时间
    t1_count = t1.hour * 60 * 60 + t1.minute * 60 + t1.second
    # t2的时间
    t2_count = t2.hour * 60 * 60 + t2.minute * 60 + t2.second
    print(t1_count, t2_count)
    # t1比t2大返回True, 使用短路运算.
    return t1_count > t2_count or False


if __name__ == '__main__':
    main()

16.2 纯函数
在下面几节中, 我们会编写两个用来增加时间值的函数.
它们展示了两种不同类型的函数: 纯函数和修改器. 
它们也展示了我会称为'原型和补丁'(prototype and patch)的开发计划.
这是一种对应复杂问题的方法, 从一个简单的原型开始, 并逐渐解决更多的复杂情况.

下面是add_time的一个简单原型:
def add_time(t1, t2):
	sum = Time()
	sum.hour = t1.hour + t2.hour
	sum.minute = t1.minute + t2.minute
	sum.second = t1.second + t2.second
	return sum
	
这个函数创建一个新的Time对象, 初始化它的属性, 并返回这个新对象的一个引用.
这个被称为一个'纯函数', 因为它除了返回一个值之外, 并不修改作为实参传入的任何对象, 
也没有任何如显示值或获得用户输入之类的副作用.

为了测试这个函数, 我将创建两个Time对象:
start, 存放一个电影( Monty Python and the Holy Grail)的开始时间;
duration, 存放电影的播放时间, 在这里是1小时35分钟.

add_time计算出电影何时结束.
>>> start = Time()
>>> start.hour = 9
>>> start.minute = 45
>>> start.second = 0

>>> duration = Time()
>>> duration.hour = 1
>>> duration.minute = 35
>>> duration.second = 0

>>> done = add_time(start, duration)
>>> print_time(done)
10:80:00

结果10:80:00可能并不是你所期望的.
问题在于这个函数并没有处理好秒数或者分钟数超过60的情况.
当发生时, 我们需要将多余的秒数'进位'到分钟数, 将多余的分钟数'进位'到小时数.

下一个是改进的版本:
def add_time(t1, t2):
    sum = Time()
    sum.hour = t1.hour + t2.hour
    sum.minute = t1.minute + t2.minute
    sum.second = t1.second + t2.second

    if sum.second >= 60:
        sum.second -= 60
    sum.minute += 1

    if sum.minute >= 60:
        sum.minute -= 60
        sum.hour += 1

    return sum

虽然这个函数是正确的, 它已经开始变大了. 
我们会在后面看到一个更短的版本.
16.3 修改器
有时候用函数修改传入的参数是很有用的. 在这个情况下, 修改对调用者是可见的.
这样的工作的函数称为修改器(modifile).
函数increment给一个Time对象增加指定的秒数, 可以自然地写为一个修改器.
下面是一个初稿:
# 给时间对象增加秒数.
def increment(time, second):
	time.second += seconds
	
	if time.second >= 60:
		time.second -= 60
		time.minute += 1
	
	if time.minute >= 60:
		time.minute -= 60
		time.hour += 1
	
第一行进行基础操作; 后面的代码处理我们前面看到的特殊情况.
这个函数正确吗? 如果seconds比60大很多, 会发生什么? (时间不是所期望的.)

在那种情况下, 只进位一次是不够的; 我们需要重复进位, 知道time.second比60.
一个办法是使用while语句替代if语句. 那样会让韩素变正确, 但并不很高效.

作为练习, 编写正确的increment版本, 并不包含任何循环.
class Time:
    """"""


def print_time(time_obj):
    print('%.2d:%.2d:%.2d' % (time_obj.hour, time_obj.minute, time_obj.second))


def increment(time, seconds):
    time.second += seconds
    # divmod求余数, (商, 余数)
    
    # 设置分钟与秒
    quotient, remainder = divmod(time.second, 60)
    time.second = remainder
    time.minute += quotient

    # 小时与分钟
    quotient, remainder = divmod(time.minute, 60)
    time.hour += quotient
    time.minute = remainder

    return time


def main(seconds):
    time_obj = Time()
    # 为time对象赋值属性
    time_obj.hour = 11
    time_obj.minute = 59
    time_obj.second = 30

    res = increment(time_obj, seconds)
    print_time(res)


if __name__ == '__main__':
    main(9999)  # 14:46:09

任何可以使用修改器做到的功能都可以使用纯函数实现.
事实上, 有的编程语言只允许使用纯函数.
有证据表明使用纯函数的程序比使用修改器的程序开发更快, 错误更少.
但有时候修改器还是很方便的, 并且函数式程序的运行效率不那么高,

总的来说, 我推荐你只要合理的时候, 都尽量编写纯函数, 而只在有绝对说服力的原因时才使用修改器.
这种方法可以称为'函数式编程风格'.
作为练习, 写一个incrment的纯函数版本, 创建并返回一个新的Time对象而不是修改参数.
(纯函数不修改传入参数的值, 修改器修改传入参数的值.)
提示: 在函数中新建Time对象, 为这个对象赋值属性, 最后返回这个新对象.
class Time:
    """"""


def print_time(time_obj):
    print('%.2d:%.2d:%.2d' % (time_obj.hour, time_obj.minute, time_obj.second))


def increment(time, seconds):
    # 新建time对象
    new_time = Time()
    # 总秒数
    sum_second = time.second + seconds
    # divmod求余数, (商, 余数)
    # 求分钟与秒
    minute, second = divmod(sum_second, 60)

    # 总分钟
    sum_minute = time.minute + minute
    # 求小时与分钟
    hour, minute = divmod(sum_minute, 60)

    # 为新对象设置属性
    new_time.second = second
    new_time.minute = minute
    new_time.hour = time.hour + hour

    return new_time


def main(seconds):
    time_obj = Time()
    # 为time对象赋值属性
    time_obj.hour = 11
    time_obj.minute = 59
    time_obj.second = 30

    res = increment(time_obj, seconds)
    print_time(res)


if __name__ == '__main__':
    main(9999)  # 14:46:09

16.4 原型和计划
刚才我展示的开发计划为'原型和补丁'.
对每个函数, 我编写一个可以进行基本计算的原型, 再测试它, 从中发现错误并打补丁.

这种方法在对问题的理解并不深入时尤其有效.
但增量地修改可能会导致代码过度复杂(因为它们需要处理很多特殊情况),
并且也不够可靠(因为很难知道你是否已经找到了所有的错误).
另一种方法是'有规划开发'(designed devwlopment).
对问题有更高阶的理解能够让编程简单得多.
在上面的问题中, 如果更深入地理解, 可以发现Time对象实际上是六十进制数里的3位数
(参见http://en.wikipedia.org/wiki/Sexagesimal)!
second属性是'个位数', minute属性是'60位数', 而hour属性是'360位数'.
在编写add_time和increment时, 我们实际上是在六十进制上进行加减, 因此才需要从一位到另一位.
这个观察让我们可以考虑整个问题的另一个中解决方法-我们将Time对象转换为整数, 
并利用计算机知道如何做整数运行的事实.
def time_to_int(time):
    minutes = time.hour * 60 + time.minte
    
    seconds = mintes * 60 + time.second
    
    return seconds

而下面是一个将整数转换回Time对象的函
(记着divmod函数将第一个参数除以第二个参数, 并以元组的形式返回商和余数):
def int_to_time(seconds):
	time = Time()
	minutes, time.second = divmod(seconds, 60)
	time.hour, time.minute = divmod(minutes, 60)
	return time
	
你可能会思考一下, 并运行一些测试, 来说服自己这些函数是正确的.
一种测试它们的方法是对很多x值检查 time_to_int(int_to_time(x)) == x.
这是一致性检验的一个例子.
一旦确认他们是正确的, 就可以使用他们重写add_time:
def add_time(t1, t2):
	# 将时间对象转换为秒
	seconds = timr_to_int(t1) + time_to_int(t2)
    # 将秒转换为时间对象
	return int_to_time(seconds)

这个版本比最初版本短的多, 并且也很容易检验.
作为练习, 使用time_to_int和int_to_time重写increment函数.
class Time:
    """"""


def print_time(time_obj):
    print('%.2d:%.2d:%.2d' % (time_obj.hour, time_obj.minute, time_obj.second))


def time_to_int(time):
    minutes = time.hour * 60 + time.minute
    seconds = minutes * 60 + time.second

    return seconds


def int_to_time(seconds):
    time = Time()
    
    minutes, time.second = divmod(seconds, 60)
    time.hour, time.minute = divmod(minutes, 60)
    
    return time


def increment(time, seconds):
    # 将时间对象转换为秒
    seconds = time_to_int(time) + seconds
    # 将秒转换为时间对象
    return int_to_time(seconds)


def main(seconds):
    time_obj = Time()
    # 为time对象赋值属性
    time_obj.hour = 11
    time_obj.minute = 59
    time_obj.second = 30

    res = increment(time_obj, seconds)
    print_time(res)


if __name__ == '__main__':
    main(9999)  # 14:46:09

从某个角度看, 在六十进制和十进制之间来会转换比只处理时间更难.
进制转换更加抽象; 我们对时间值的直觉更好.

但如果我们将时间看作六十进制数, 并做好编写转化函数(time_to_int和int_to_time)的先期投入,
就能得到一个更短, 更可读, 也更可靠的函数.

它也让我们今后更容易添加功能. 
(将时间表示为六十进制数并实现转换函数可以为今后添加更多功能提供方便,
因为将时间表示为六十进制数可以使得时间的处理更加统一化, 简化了程序实现的复杂性.)

例如, 假设将两个Time对象相减来获取它们之间的时间间隔.
简单得做法是使用借位实现减法. 而使用转换函数则更简单且更容易正确.

讽刺的是, 有时候把一个问题弄的更难(或者更通用)
反而会让他更简单(因为会有更少的特殊情况以及更少的出错机会).
16.5 调试
一个Time对象但minute当second的值在060之间(包好0但不包含60)以及hour是正值时, 是合法的.
hour和minute应当是整数值, 但我们也许需要允许second拥有小数值.

这些需求称为'不变式', 因为他们应当总为真.
换句话说, 如果它们不为真, 则一定有什么地方出错了.

编写代码来检查不变式可以帮你探测错误并找寻它们的根源.
例如, 你可以写一个像valid_time这样的函数, 接收Time对象, 并在它违反了一个不变式时, 返回False:
def valid_time(time):
	# 时分秒如果大于0, 返回False.
	if time.hour < 0 or time.minute < 0 or time.second < 0:
		return Faalse
		
	# 时分如果大于等于60, 返回False.
	if time.minute >= 60 time.second >= 60:
		return False
	
	return True
	
接着在每个函数的开头, 可以检查参数, 确保它们是有效的:
def add_time(t1, t2):
    
	if not valid_time(t1) or not valid_time(t2):
		raise ValueRrror('invalid Time object in add_time')
        
     seconds = time_to_int(t1) + time_to_int(t2)
    
    return int_to_time(seconds)

或者可以使用一个assert语句.
它会检查一个给定的不变式, 并但检查失败时抛出异常:
def add_time(t1, t2):
	# asser后面的表达式结果必须为正
	assert valid_time(t1) and valid_time(t2)
	
	seconds = time_to_int(t1) + time_to_int(t2)
    
    return int_to_time(seconds)

assert语句很有用, 因为它们区分了处理普通条件的代码和检查错误的代码.
16.6 术语表
原型和补丁(prototype and patch): 一种开发计划模式, 先编写程序的粗略原型, 并测试, 则找到错误时更正.

有规划开发(planned development): 一种开发计划模式, 先对问题有了高阶的深入理解,
	并且比增量开发或者原型开发有更多的规划.

纯函数(pure function): 不修改任何形参对象的函数. 大部分纯函数都有返回值.

修改器(modifier): 修改一个或多个形参对象的函数. 大部分修改器都不返回值, 也就是返回None.

函数式编程风格(functional proframming style): 一种编程风格, 其中大部分函数都是存函数.

不变式(invariant): 在程序的执行过程中应当总是为真的条件.

assert语句(assert statement): 一种检查某个条件, 如果检查失败则抛出异常的语句.
16.7 练习
本章中的代码示例可以从↓下载.
https://github.com/AllenDowney/ThinkPython2/blob/master/code/Time1.py 
这些练习的解答可以从↓下载.
https://github.com/AllenDowney/ThinkPython2/blob/master/code/Time1_soln.py
1.练习1
编写一个函数mul_time接收一个Time对象以及一个整数, 返回一个新的Time对象,
包含原始时间和整数的乘积. (时间对象转为秒 * 整数)

然后使用mul_time来编写一个函数, 接收一个Time对象表示一场赛车的结束时间, 
以及一个表示距离的数字, 并返回一个Time对象表达平均节奏(每英里花费的时间).

(正赛的距离不能少于305公里, 不能大于320公里, 时间不能少于1个小时10分钟, 不能大于2个小时.
1千米(公里)=0.621371192237英里)
import copy


class Time:
    """"""


def print_time(time_obj):
    print('%.2d:%.2d:%.2d' % (time_obj.hour, time_obj.minute, time_obj.second))


def time_to_int(time):
    minutes = time.hour * 60 + time.minute

    seconds = minutes * 60 + time.second

    return seconds


def mul_time(t1, num):
    t2 = copy.copy(t1)
    # 将时间转为十进制整数

    seconds = time_to_int(t2)
    # 乘积
    t2.product = seconds * num

    return t2


def main(num):
    time_obj = Time()
    # 为time对象赋值属性
    time_obj.hour = 11
    time_obj.minute = 59
    time_obj.second = 30

    t2 = mul_time(time_obj, num)
    print_time(t2)
    print(t2.product)  # 388530


if __name__ == '__main__':
    main(9)  

import copy


class Time:
    """"""


def print_time(time_obj):
    print('%.2d:%.2d:%.2d' % (time_obj.hour, time_obj.minute, time_obj.second))


def time_to_int(time):
    minutes = time.hour * 60 + time.minute

    seconds = minutes * 60 + time.second

    return seconds


def mul_time(t1, mile):
    t2 = copy.copy(t1)
    # 将时间转为十进制整数, 比赛的总秒数.
    seconds = time_to_int(t2)
    # 车每秒跑的距离 0.02773... 英里
    distance = mile / seconds

    # 一公里需要的时间 36.059... 秒
    t2.average_time = 1 / distance

    return t2


def main(num):
    time_obj = Time()
    # 比赛时间
    time_obj.hour = 1
    time_obj.minute = 59
    time_obj.second = 30

    # 公路转英里 320 --> 198.83
    mile = num * 0.621371192237

    t2 = mul_time(time_obj, mile)
    print('每英里花费%.3f秒!' % t2.average_time)  # 每英里花费36.059秒!


if __name__ == '__main__':
    # 比赛的公里数
    main(320)

2. 练习2
datetime模块提供了time对象, 和本章中的Time对象类似, 但它们提供了更丰富的方法和操作符.
在https://docs.python.org/3/library/datetime.html阅读相关文档.

1. 使用datetime模块来编写一个程序获取当前日期并打印出今天是周几.

2. 编写一个程序接收生日作为输入, 并打印出用户的年龄, 
   以及到他们下一次生日还需要的天数, 小时数, 分钟数和秒数.

3. 对于生于不同天的两个人, 总有一天, 一个人的年龄是另一个人的两倍.
   我们称这是他们的'双倍日'. 编写一个程序接收两个生日, 并计算出它们的'双倍日'.

(数学不好不写了...)
4. 在增加一点挑战, 编写一个更通用的版本, 计算一个人比另一个人大n倍的日子(n倍日).
解答:  https://github.com/AllenDowney/ThinkPython2/blob/master/code/double.py
# 计算今天是星期几
import datetime

# 获取今天的日期对象
today = datetime.date.today()
print(today)  # 2023-04-18

# 计算今天是星期几
weekday = today.weekday()
# 输出0-6, 0时星期1
print('今天是星期%s.' % weekday + 1)  # 今天是星期1.

# 计算离下一次生日的时间
from datetime import datetime


def main():
    print("今天是星期", end='')
    today = datetime.today()
    print(today.weekday() + 1)

    # s = input('以"年-月-日"的格式输入你的生日: ')
    s = '1997-03-26'
    # 按%Y-%m-%d 年月日格式生成日期对象, 连字符可以自定义, 对应上面的字符串即可.
    bday = datetime.strptime(s, '%Y-%m-%d')

    # 替换日期对象中的年份为今年
    next_bday = bday.replace(year=today.year)
    # 如果今天的日期比生日大, 则说明今年生日已经过了, 要到下一年才过生日, 年份加1
    if next_bday < today:
        next_bday = next_bday.replace(year=today.year + 1)

    # date()方法展示日期.
    print("你的下一个生日为: %s." % next_bday.date())

    # 计算离生日还有多少天
    until_next_bday = next_bday - today
    # days展示时间
    print('离生日还有%s天.' % until_next_bday.days)

    age = today.year - bday.year
    print("你现在的年龄:%s岁." % age)


if __name__ == '__main__':
    main()

# 计算双倍日
from datetime import datetime


def main():
    print("在这些日期出生的人:")
    bday1 = datetime(day=11, month=5, year=1967)
    bday2 = datetime(day=11, month=10, year=2003)
    print(bday1.date())
    print(bday2.date())

    print("双倍日是:", end='')
    # 小的给d1
    d1 = min(bday1, bday2)
    # 大的日期给d2
    d2 = max(bday1, bday2)
    # 计算两个人的年龄差.
    dd = d2 + (d2 - d1)
    print(dd.date())

    print('年纪大的活了%s天.' % (dd - d1).days)
    print('年纪小的活了%s天.' % (dd - d2).days)


if __name__ == '__main__':
    main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/712969.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(源码)供应商电子招投标管理系统实现方案和功能说明

采购在线招投标供应商管理系统是一个集成了多个关键功能的综合性系统&#xff0c;旨在优化采购流程、提高效率和确保透明度。以下是关于您提到的五个核心功能的详细解释&#xff1a; 供应商管理 此功能允许企业记录和管理供应商的基本信息&#xff0c;如公司名称、联系方式、主…

了解并解决 Flutter 中的灰屏问题

生产中的 flutter 应用程序中的灰屏是一种通用占位符&#xff0c;当框架遇到问题无法渲染预期用户界面时就会显示。是的&#xff0c;所以基本上是出现问题时的后备指示器。 有趣的是&#xff0c;这只出现在发布模式下。在任何其他模式下运行都会显示红色错误屏幕&#xff0c;并…

apt-get update和apt-get upgrade的区别

apt-get update apt-get update 命令用于更新本地软件包列表。具体来说&#xff0c;做了以下事情&#xff1a; ①从 /etc/apt/sources.list 文件和 /etc/apt/sources.list.d/ 目录下的所有文件中读取软件源配置。 ②连接到这些软件源&#xff0c;并下载最新的软件包列表。 ③将…

前端老古董execCommand——操作 选中文本 样式

文章目录 ⭐前言⭐exe command api用法&#x1f496; example示例&#x1f496; 测试效果 ⭐execommand和getSelection 的联系⭐总结⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文分享关于 前端老古董execCommand——操作选中文本。 execommand 当一个 HTML 文…

【Linux】进程_4

文章目录 五、进程4. 进程状态5. 进程优先级6. 进程的调度和转换 未完待续 五、进程 4. 进程状态 当进程属于挂起状态时&#xff0c;进程的可执行程序代码和数据均会被从内存中换入到磁盘中&#xff0c;此时进程的PCB并没有消失&#xff0c;只要操作系统还需要管理这个进程&a…

ChatGPT关联技术

ChatGPT关联技术 一、前馈神经网络二、序列到序列模型&#xff08;Seq2Seq&#xff09;三、自注意力机制四、多头自注意力机制五、自监督学习六、Transformer模型七、语言生成技术八、多语种语言模型九、预训练语言模型十、生成式预训练模型&#xff08;GPT&#xff09;十一、近…

【odoo】odoo.conf文件配置

概要 odoo.conf 文件是 Odoo 服务器的配置文件&#xff0c;它用于定义和管理 Odoo 运行时的各种参数。这个文件包含了许多配置选项&#xff0c;可以帮助管理员根据特定的需求和环境来调整 Odoo 服务器的行为。 主要功能 数据库连接设置&#xff1a;定义 Odoo 连接到 PostgreSQL…

使用tkinter创建带有图标的菜单栏

使用tkinter创建带有图标的菜单栏 效果代码代码解析创建主窗口加载图标创建菜单栏添加文件菜单添加带图标的菜单项 Tkinter 的默认菜单外观较为简单&#xff0c;可以通过自定义和添加图标&#xff0c;让菜单显示更好看。 效果 代码 import tkinter as tk from tkinter import …

【SpringBoot】SpringBoot:构建安全的Web应用程序

文章目录 引言为什么需要安全Spring Security概述配置Spring Security添加依赖基本配置 用户认证创建用户实体类创建用户存储库自定义用户服务更新安全配置 用户授权更新用户实体类更新自定义用户服务更新安全配置 防护措施防止SQL注入使用参数化查询 防止跨站脚本&#xff08;…

Java17 --- RabbitMQ之插件使用

目录 一、Federation插件 1.1、运行两个rabbitmq实例 1.2、启用插件 1.3、在下游端点添加上游端点 1.4、创建策略 1.6、测试 二、联邦队列 2.1、创建策略 2.2、创建交换机与队列 2.2.1、创建52000的队列与交换机 2.2.2、创建62000的队列 三、Shovel 3.1、启…

WNR最便捷美观的开源桌面计时器工具

华丽外观&#xff0c;功能全面。工作和休息的完美计时器。跨平台支持&#xff0c;无论是Windows、Mac还是Linux&#xff0c;WNR都能轻松驾驭。 超强全屏专注模式 对于寻找高效工作/休息管理工具却屡屡受挫的用户&#xff0c;WNR的“全屏专注模式”无疑是终极解决方案。它确保在…

Android 蓝牙配对Settings应用里面的简要流程记录

Android 蓝牙配对Settings应用里面的简要流程记录 文章目录 Android 蓝牙配对Settings应用里面的简要流程记录一、前言二、Settings蓝牙配对的关键代码1、接收蓝牙请求的地方 AndroidManifest.xml2、BluetoothPairingRequest3、BluetoothPairingService4、BluetoothPairingDial…

利用机器学习重构视频中的人脸

引言 中国与英国的研究团队携手合作&#xff0c;开创了一种创新的视频面孔重塑技术。这项技术能够以极高的一致性对视频中的面部结构进行逼真的放大和缩小&#xff0c;且避免了常见伪影的产生。 从研究人员选取的YouTube视频样例中可见&#xff0c;经过处理后&#xff0c;女演…

LC1020:飞地的数量

题目 给你一个大小为 m x n 的二进制矩阵 grid &#xff0c;其中 0 表示一个海洋单元格、1 表示一个陆地单元格。 一次 移动 是指从一个陆地单元格走到另一个相邻&#xff08;上、下、左、右&#xff09;的陆地单元格或跨过 grid 的边界。 返回网格中 无法 在任意次数的移动…

在ubuntu中启动docker的mysql8镜像

首先查看docker是否启动&#xff1a; docker ps #出现信息就是启动成功 启动命令&#xff1a; sudo systemctl start docker 设置开机自启&#xff1a; sudo systemctl enable docker 查询下载好的mysql8的镜像文件&#xff1a; docker images 在启动查询好的镜像文件&#…

Oracle--19C在Centos7上的静默安装(rpm版)

一、Oracle 19c Linux安装&#xff08;Centos 7&#xff09; 1.查看磁盘可用空间及配置ip地址 [rootlocalhost /]# df -h 文件系统 容量 已用 可用 已用% 挂载点 devtmpfs 1.4G 0 1.4G 0% /dev tmpfs 1.4G …

【Pytorch】一文向您详细介绍 model.eval() 的作用和用法

【Pytorch】一文向您详细介绍 model.eval() 的作用和用法 下滑查看解决方法 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通本硕…

桂电人工智能学院大数据实验,使用 Docker 搭建 hadoop 集群

桂电人工智能学院大数据实验&#xff0c;使用 Docker 搭建 hadoop 集群 第一步 安装 Docker, Windows 上可以使用 Docker Desktop 下载地址&#xff1a;https://www.docker.com/products/docker-desktop/ 安装过程自行谷歌 安装好的标志&#xff1a;打开终端 运行docker p…

论文阅读:基于谱分析的全新早停策略

来自JMLR的一篇论文&#xff0c;https://www.jmlr.org/papers/volume24/21-1441/21-1441.pdf 这篇文章试图通过分析模型权重矩阵的频谱来解释模型&#xff0c;并在此基础上提出了一种用于早停的频谱标准。 1&#xff0c;分类难度对权重矩阵谱的影响 1.1 相关研究 在最近针对…

ERP、CRM、MRP、PLM、APS、MES、WMS、SRM系统介绍

一、ERP系统 ERP系统&#xff0c;即企业资源计划&#xff08;Enterprise Resource Planning&#xff09;系统&#xff0c;是一种集成管理软件系统&#xff0c;旨在帮助企业实现资源的有效管理和优化。以下是对ERP系统的详细介绍&#xff1a; 1、定义与功能 ERP是企业资源计划…