0%

html常用的标签

注释标签、文字标签和段落标签

注释标签

原文

1
2
3
4
<div class="container">
<h1>Hello, world!</h1>
<p>Welcome to my website!</p>
</div>

加上注释

1
2
3
4
<!-- <div class="container">
<h1>Hello, world!</h1>
<p>Welcome to my website!</p>
</div> -->

文字标签

格式 <font>……</font>

常用属性

color

1.使用英文单词表示 red black blue green

2.rgb(十六进制,0~9 a~f) 每两位代表一种颜色 red green blue 常用的十六进制颜色: 语法格式:#后面跟上随机6个位数

#ffffff 白色 #000000 黑色 #abcdef 天蓝色 #ff0000 红色

size

size:取值范围1~7之间 如果超出了最大值使用默认最大值7size:取值范围1~7之间 如果超出了最大值使用默认最大值7

举个例子

<font color="red" size="4">宣示—习近平发出新时代改革开放强音</font>

效果如下

宣示—习近平发出新时代改革开放强音

段落标签

格式 <p>……</p>

作用:设置文本的样式(外观) 语法格式:style='属性名:属性值;属性名2:属性值2..'

font-size:修改文字的大小 fonts-size:20px 单位像素 background-color:设置文本的背景颜色

width:设置宽度的属性
1.使用像素 800px 2.使用百分比: 80% height:设置高度的属性

举个例子

<p style="color:white;background: red;width:80%;height:200px;">新浪科技讯 北京时间12月21日早间消息,本周四,苹果宣布约翰·詹南德雷亚(John Giannandrea)进入公司执行团队。不久之前,苹果刚刚任命詹南德雷亚担任AI、机器学习战略高级副总裁。晋升之后,詹南德雷亚直接向苹果CEO库克汇报工作。</p>

效果如下

新浪科技讯 北京时间12月21日早间消息,本周四,苹果宣布约翰·詹南德雷亚(John Giannandrea)进入公司执行团队。不久之前,苹果刚刚任命詹南德雷亚担任AI、机器学习战略高级副总裁。晋升之后,詹南德雷亚直接向苹果CEO库克汇报工作。

和字体相关的其他标签

加粗

1
2
3
4
<!--加粗-->
<p>段落</p>
<b>加粗</b>
<strong>加粗2</strong>

效果

段落

加粗 加粗2

下划线

1
2
<!--下划线-->
<u>下划线</u>

效果

下划线

删除线

1
2
3
<!--删除线-->
<s>删除线</s>
市场价:<s>999</s>现价:99

效果

删除线 市场价:999现价:99

换行

1
2
3
<!--换行-->
这一举动表明苹果高度重要AI。库克在声明中说:“在苹果,约翰做得很好,<br/>
很高兴能看到他加入我们的执行团队。机器学习与AI对于苹果的未来至关重

一举动表明苹果高度重要AI。库克在声明中说:“在苹果,约翰做得很好,
很高兴能看到他加入我们的执行团队。机器学习与AI对于苹果的未来至关重

上标和下标

1
2
3
<p><sup>上标</sup>
正常显示的文字
<sub>下标</sub></p>

效果

上标 正常显示的文字 下标

斜体

1
2
3
<!--斜体-->
<i>斜体</i>
<em>斜体2</em>

斜体 斜体2

缩进

1
2
3
<!--缩进-->
<blockquote>詹南德雷亚在谷歌工作8年,4月份加入苹果。在谷歌工作时,他曾经是搜索、机器智能与研发主管。跳到苹果之后,詹南德雷亚对Siri、Core Ml负责。
</blockquote>

效果

詹南德雷亚在谷歌工作8年,4月份加入苹果。在谷歌工作时,他曾经是搜索、机器智能与研发主管。跳到苹果之后,詹南德雷亚对Siri、Core Ml负责。

标题标签和字符实体

标题标签:<hn></hn> 注意:n的取值范围为1~6的整数

举例

1
2
3
4
5
6
<h1>标题1</h1>
<h2>标题2</h2>
<h3>标题3</h3>
<h4>标题4</h4>
<h5>标题5</h5>
<h6>标题6</h6>

效果

标题1

标题2

标题3

标题4

标题5
标题6

字符实体

特殊字符

1
2
&lt ---> <
&gt ---> >

版权

1
2
<!--版权-->
<p>&copy;北京清华出版社</p>

效果

©北京清华出版社

空格

1
2
<!--空格-->
<p>&nbsp;&nbsp;&nbsp;&nbsp;一名在美中国公民被控窃取商业机密,美方称涉案达18亿</p>

    一名在美中国公民被控窃取商业机密,美方称涉案达18亿

双引号

1
2
<!--双引号-->
<p>&quot;华为回应部分国际银行断交:公司经营稳健,业务运转正常&quot;</p>

"华为回应部分国际银行断交:公司经营稳健,业务运转正常"

和号

1
2
<!--和号-->
<p>11人跨省全链条制贩毒网络团伙&amp;被摧毁,头目是前知名歌手</p>

11人跨省全链条制贩毒网络团伙&被摧毁,头目是前知名歌手

图像标签和路径

图像标签

格式<img……/>

作用:显示网页上面的图片

常用属性

1.src:图片的路径 2.width:设置图片的宽度 3.height:设置图片的高度 4.alt:图片的替换文本,如果图片资源加载不出来,显示文本 5.title:鼠标悬浮标题

举例

1
2
3
4
5
6
7
8
9
10
11
<!--直接设置网页上显示图片,使用图片默认宽高-->
<img src="img/pic.jpg" />

<!--使用width和height-->
<img src="img/pic4.jpg" width="100px" height="100px" />

<!--图片替换文本-->
<img src="img/pic33.jpg" alt="圣诞节快乐" />

<!--鼠标悬浮标题-->
<img src="img/pic2.jpg" title="美女与野兽" width='200px' height='200px'/>

多态

python的多态与java的多态类似。比如一种常见的使用形式就是在函数传参的时候传递的可以是父类和继承该父类的多种子类。然而python比java更灵活

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
定义:
多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)

例如:
序列有多种形态:字符串,列表,元祖
动物有多种形态:人,猪,狗

多态和多态性的区别:
多态:同一种事物的多种形态,动物分为人类,猪类(在定义角度)
多态性:一种调用方式,不同的执行效果(多态性)

"""
面向对象的三大特征:封装,继承,多态

封装:又称为信息的隐藏,类的实现和使用时分开的,类提供了外部访问的方法,调用者不需要关注
类里面的具体实现,会调用即可

生活中封装:买手机会用就可以

继承:一个类继承另外一个类,被继承的类称为父类或者基类,继承的类称为子类或者派生类,
子类可以共享父类里面受保护,公有属性和方法,子类不能共享父类私有属性和方法
继承可以减少代码的书写,提高代码的可维护性

多态:同一种事物有多种形态
多态性:同一种调用方式,返回不同的结果
多态的前提:继承和重写
"""
#多态:一种事物有多种表现形式
#定义一个父类
class Animal(object):
#定义一个普通方法
def sayHello(self):
pass

#定义一个子类Person,继承父类Animal
class Person(Animal):
#重写父类同名的方法
def sayHello(self):
print('hello,i am Person')

#定义一个子类Pig,继承父类Animal
class Pig(Animal):
#重写父类同名的方法
def sayHello(self):
print('aoao,i am Pig')

#定义一个子类Dog,继承父类Animal
class Dog(Animal):
#重写父类同名的方法
def sayHello(self):
print('wangwang,i am Dog')

#实例化不同子类创建对象
Per = Person()
Pi = Pig()
Do = Dog()
# Per.sayHello()
# Pi.sayHello()
# Do.sayHello()

#多态性:同一种调用方式,返回不同的结果
def func(o): #python是动态语言,o是多态性的体现,这里不需要指定类型,参数的类型由调用者传的值决定
o.sayHello()

func(Per)
func(Pi)
func(Do)

#多态的好处
class Cat(Animal): #继承父类Animal重新定义子类Cat
def sayHello(self):
print('mimi,i am Cat')

#创建一个Cat的对象ca
ca = Cat()
func(ca)

"""
多态的好处:
1.提高代码在外部调用灵活性
2.提高代码的扩展性
"""

类属性和实例属性

类属性

定义:在类中定义的属性

举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
概述:
在类中定义的属性(公有和私有)

#定义一个人类,设置姓名和年龄属性

class Person(object):
name = 'xiaoming' #公有类属性
__age = 12 #私有类属性

#创建Person类的对象p
p = Person()
print(p.name) #实例对象访问类的公有属性
print(Person.name) #类对象访问类的公有属性

print(p.__age) #实例对象访问类的私有属性 not ok
print(Person.__age) ##类对象访问类的私有属性 not ok

实例属性

定义:定义在init初始化方法中的属性

举个例子,什么是实例属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#定义一个人类,设置姓名,年龄和地址等属性

class Person(object):
address = '上海市' #类属性

#定义初始化方法
def __init__(self,name,age):
self.name = name #实例属性
self.age = age

#创建Person类的对象pe
pe = Person('张三',30)
# print(pe.address) #通过实例对象访问类属性
# print(pe.name) #通过实例对象访问实例属性
# print(pe.age)

print(Person.address) #类在定义的时候已经产生了,类属性直接属于类
print(Person.name) #当实例化类创建对象,对属性赋值 实例属性才会产生内存里面 类访问不到实例属性
print(Person.age)

实例属性和类属性的关系:同名的情况下,实例属性会覆盖类属性

举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#定义一个人类
class Person(object):
country = 'china' #类属性

#定义初始化方法
def __init__(self):
self.country = '上海市' #实例属性

#创建Person类的对象p
p = Person()
print(p.country) #通过实例对象访问属性 输出“上海市”
print(Person.country) #类对象访问属性 输出“china”
#通过实例属性修改类属性的值
p.country = 'chinese' #实例属性会屏蔽类属性
print(p.country) # 输出“chinese”
print(Person.country) # 输出“china”

del p.country #删除实例对象
print()
print(p.country) # 输出“china”,是类对象,不是实例对象
print(Person.country) # 输出“china”

#类里面定义同名的实例属性和类属性,实例对象修改类属性,实例属性会屏蔽同名类属性
#实例属性优先级高于类属性

静态方法和类方法

类方法

定义

概述: 类对象所拥有的方法,需要使用到修饰器 @classmethod---->类方法 对于类方法,第一个参数必须是类对象,一般以cls表示作为第一个参数(当然可以用其他的名字,但是不建议修改)

举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 定义一个人类

class Person(object):
country = 'china' # 类属性

@classmethod
def getCountry(cls):
return cls.country

@classmethod
def setCountry(cls, country):
cls.country = country


# 创建Person对象
p = Person()
print(p.getCountry()) # 通过实例对象访问类方法 输出“china”
print(Person.getCountry()) # 通过类对象访问类方法 输出“china”

p.setCountry('chinese')
print(p.getCountry()) # 输出"chinese"
print(Person.getCountry()) # 输出“chinese”

# 总结:类方法可以修改类属性

静态方法

定义:通过修饰器@staticmethod来进行修饰,不需要传参数

举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
概述:
需要通过修饰器@staticmethod来进行修饰,不需要传参数

#定义一个人类
class Person(object):
country = 'china' #类属性

@staticmethod
def getCountry():
return Person.country

#创建Person类的对象
p = Person()
print(p.getCountry()) #通过实例对象访问静态方法

总结

类方法:声明方法之前,需要使用到修饰器 @classmethod,里面第一个参数类对象cls,类对象访问的是类属性或者类方法 实例方法:隐含传递的参数是self,对象本身,self访问的可能是实例属性,也有可能是类属性,类方法,静态方法 静态方法:声明方法之前,需要使用到修饰器@staticmethod,不需要加任何参数,访问的是类属性的引用,只能通过类对象调用

__slots__

定义:限制实例属性

语法格式:slots = ('属性1','属性2')

__slots__属性限制添加属性只对当前类的实例对象起作用,对类属性,继承的子类实例对象不起作用的

举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
动态语言:可以在运行的过程中,修改代码
静态语言:编译时已经确定的代码,运行的时候不能修改

如果我们想要限制实例属性?
允许对Person实例中添加name和age属性,
python允许定义class的时候,定义一个特殊的变量---->__slots__,限制class能够添加的属性

语法格式:__slots__ = ('属性1','属性2')

#定义一个人类,只允许添加姓名和年龄属性

class Student(object):
__slots__ = ('name','sex') #限制当前类添加的属性

#通过Student类创建对象stu
stu = Student()
#往对象里面添加属性
stu.name = '张三'
stu.sex = '男'
print(stu.name)
print(stu.sex)
#增加一个新的属性
# stu.weight = '80kg' #报错,类中限制添加属性没有weight
# print(stu.weight)
Student.weight = '50kg' # 添加类属性
print(stu.weight)

#定义一个子类demo,继承Student
class Demo(Student):
pass
d = Demo()
d.height = '180'
print(d.height)

"""
注意:__slots__属性限制添加属性只对当前类的实例对象起作用,对类属性,继承的子类实例对象不起作用的
"""

@property

私有属性添加getter和setter方法

python中和java类似的是私有属性不能直接修改,需要调用专门的方法才能修改;但python相对于java做出了优化,通过property函数创建一个特性(property),将 getMoney 方法作为获取属性值的方法,setMoney 方法作为设置属性值的方法。这样就可以像访问普通属性一样来访问 Money 类中的 money 属性

举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#定义一个money类,设置一个私有的__money属性

class Money(object):
#定义一个初始化方法
def __init__(self):
self.__money = 0

#定义对属性设置的方法
def setMoney(self,value):
if isinstance(value,int) or isinstance(value,float):
self.__money = value
else:
print('Error:金额只能是整形或者浮点型')

#定义方法获取属性值
def getMoney(self):
return self.__money

#添加实例属性
money = property(getMoney,setMoney)

#通过Money类创建对象mo
mo = Money()
# print(mo.__money) #实例对象不能访问类的私有属性
mo.setMoney(100)
print(mo.getMoney()) # 输出100

# 下面这两行代码看似是直接修改了对象的私有属性,实际上是先调用了getMoney和setMoney方法
mo.money = 500
print(mo.money) # 输出500

使用property取代getter和setter方法

取代set/get------》修饰器-----》@property @property--->属性函数,可以对属性赋值时候做必要的检查,并保证代码的清晰简短 作用: 1.将方法转化为只读 2.重新实现一个属性的设置和读取方法,可做边界判定

举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Money(object):
#定义初始化方法
def __init__(self):
self.__money = 0

@property
def money(self): #相当于获取元素值方法
return self.__money

@money.setter #money是上面取值的方法名 赋值的方法
# @money.setter是一个装饰器,用于指定一个方法作为属性的设置方法
def money(self,value):
if isinstance(value,int) or isinstance(value,float):
self.__money = value
else:
print('Error:不是整形也不是浮点型')
# 上面两个方法同名,第一个用来获取元素,第二个用来设置元素的值,然后在外界看起来虽然是私有属性的money和实例属性并无区别
#通过Money创建对象m
m = Money()
print(m.money)
m.money = 16888
print(m.money)

发送邮件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#导入邮件库
import smtplib
#导入邮箱文本
from email.mime.text import MIMEText

#设置邮箱服务器 qq/126/163/gmail/yahoo/阿里云
SMTPServer = 'smtp.163.com'
#设置发送邮箱的地址
sender = 'ztb0016@163.com'
#设置发送邮箱的通行码,不是密码
password = 'GTTULMLHIKOZSXIZ'


#设置发送的内容
message = '你是一个好人123333...'
#转换成人能够看懂的格式
msg = MIMEText(message)
#设置发送邮件的主题
msg['subject'] = '来自一位帅哥的表白33333'
#发送者
msg['from'] = sender

#设置邮箱服务器, 25表示的是端口
emailServer = smtplib.SMTP(SMTPServer,25)
#登录邮箱
emailServer.login(sender,password)
#发送邮件的内容
emailServer.sendmail(sender,['piolet0016@gmail.com'],msg.as_string())
#关闭邮箱
emailServer.quit()

用列表模拟栈

append模拟入栈

pop模拟出栈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
"""
栈--->有名堆栈
原理:先进后出

装子弹
"""
#使用列表模拟堆栈
#入栈
# stack = []
# stack.append('A')
# stack.append('B')
# stack.append('C')
# print(stack)
#
# #出栈
# stack.pop()
# print(stack)
import os
def getAllFileDir(path):
stack = []
#入栈
stack.append(path)
#处理栈,当栈为空的时候结束操作
while len(stack) != 0:
#出栈
outDir = stack.pop()
#获取当前目录所有文件
filelist = os.listdir(outDir)
#判断哪些是目录,继续入栈,如果是文件直接打印
for fileName in filelist:
#判断文件是否是路径(用绝对路径)
fileAbsPath = os.path.join(outDir,fileName)
if os.path.isdir(fileAbsPath):
print('目录:',fileName)
#入栈
stack.append(fileAbsPath)
else:
print('文本文件:',fileName)
#调用函数
getAllFileDir('C:\python课程大纲\python课程大纲')

专门模拟队列的

定义一个队列

1
2
import collections
queue = collections.deque()

入队

1
queue.append(path)

出队

1
outDir = queus.popLeft()

具体事例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
"""
队列原理:先进先出
#银行办理业务排队

collections
deque() 创建一个队列
append() 队列添加元素
popLeft() 从队列里面删除元素
len() 获取长度

listdir()获取当前目录下所有的文件
isdir()判断是否是目录
"""
import collections
import os
def getAllFileDir(path):
#创建一个队列
queue = collections.deque()
#入队
queue.append(path)
#处理队列,如果队列为空结束操作
while len(queue) != 0:
#出队
outDir = queue.popleft()
#获取当前目录下所有的文件
filelist = os.listdir(outDir)
#判断哪些是目录,入队,如果是文件直接打印
for fileName in filelist:
#判断是否是路径(用绝对路径)
fileAbsPath = os.path.join(outDir,fileName)
if os.path.isdir(fileAbsPath):
print('目录:',fileName)
#入队
queue.append(fileAbsPath)
else:
print('文本文件:',fileName)
#调用函数
getAllFileDir('C:\python课程大纲\python课程大纲')

高阶函数

map

定义:根据提供的函数对指定的序列做映射

格式

map(function,iterable) function---》函数,两个参数---》返回值是一个新的列表 iterable---》一个或者多个序列

python2:返回列表 python3:返回的是迭代器

举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
li = [1,2,3,4]
#案例1:计算列表各个元素的平方
#定义一个求平方的函数
def square(n):
return n ** 2

res = map(square,li) #将li列表里面每个元素先作为square函数参数,获取每个元素平方,再执行map函数
print(res) #输出<map object at 0x000002C8C4875CC0>
print(tuple(res)) #输出(1, 4, 9, 16)
print(list(res)) #输出[]
#案例2:将单个字符转换为对应的字面量整数
li2 = ['1','2','3','4']
#定义一个函数
def chrToInt(str):
return {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5}[str]
res2 = map(chrToInt,li2)
# print(list(res2))

#案例3:将整数元素的序列,转换为字符串类型
#[1,2,3,4]--->['1','2','3','4']
res3 = map(str,[1,2,3,4])
print(tuple(res3))

reduce

定义:reduce()函数会对参数中的元素进行累积

函数将一个数据集合(列表,元组)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。

格式:

reduce(function,iterable,[initializer]) function:函数,有两个参数 iterable:可迭代的对象 initializer:可选,初始化参数

举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from functools import reduce
#案例1:两个数的求和
def add(a,b):
return a + b
res = reduce(add,range(1,101))
print(res)

#案例2:获取每一个词出现的次数(空格)
str = 'hello python hello php python aa ss aa'
list = str.split(' ')
print(list)

#定义一个函数
def func(x,y):
if y in x:
x[y] += 1
else:
x[y] = 1
return x
res3 = reduce(func,list,{})
# reduce 函数的工作流程是:
# 将初始值 {} 和列表中的第一个元素传递给函数 func 进行处理,得到一个新的结果。
# 将上一步的结果和列表中的下一个元素传递给函数 func 进行处理,得到另一个新的结果。
# 不断重复上述过程,直到列表中的所有元素都被处理完毕。
# 返回最终的结果,即字典,其中存储了每个单词的出现次数。
print(res3)

filter

定义

filter()函数:用于过滤序列,过滤掉不符合条件的元素,返回由符合条件的元素组成的新列表

格式

filter(function,iterable) function:函数 判断函数 iterable:序列,序列的每一个元素作为参数传递到函数进行判断,返回True,False,最后将返回True的元素存放到一个新的列表中

返回值

Pyhton2返回列表 Python3返回迭代器对象

举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#案例1:筛选指定的元素
list01 = [1,2,3,4,5,6,7,8,9,10]
#案例1:将偶数筛选出来,奇数删除
#定义一个函数
def even(num):
if num % 2 == 0:
return True
return False
res = filter(even,list01)
print(list(res))

#案例2:将没有爱好的信息过滤掉
list02 = [['姓名','年龄','爱好'],['xiaoming',25,'无'],['laowang',30,'写代码'],['xiaogang',29,'无']]
#定义一个函数
def test(v):
if v == '无':
return False
return True
for line in list02:
res2 = filter(test,line)
print(list(res2))
#使用匿名函数
res4 = filter(lambda x:x.isdigit(),L)
print(list(res4))

sorted

定义

sorted()函数对所有的可迭代的对象进行排序的操作 sort: 方法返回的是对已经存在的列表进行操作 sorted:返回值为一个新的list,而不是在原来的基础上进行的操作。

格式

sorted(iterable[, cmp[, key[, reverse]]]) iterable:可迭代的对象 cmp ---》比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出,此函数必须遵守的规则为,大于则返回1,小于则返回-1,等于则返回0。 key ---》主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。 reverse ---》 排序规则,reverse = True 降序 , reverse = False 升序(默认)。

举个例子

1
2
3
4
5
6
7
8
9
10
11
12
lst = [2,0,99,20,100,111]
lst.sort()
print(lst)
res = sorted(lst)
print(res)

#key接受一个内置函数进行排序
lst2 = [-3,10,8,2,111,-200]
lst2.sort()
print(lst2)
res2 = sorted(lst2,key=abs)
print(res2)

exercise1:修改类属性值的两种方式?并写出具体的代码

类属性:

和java相似的是,就是这一类公共的属性,修改这一个其他是这个类(不是同一个对象的)都会变

不同点在于java中类属性是用static修饰的,就是类属性和普通属性之间由严格的界定,而python没有

方法

  1. 直接通过类名修改类属性的值。
  2. 通过实例对象修改类属性的值(这种方式会在实例中创建同名的实例属性,并覆盖类属性)。

比如下面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MyClass:
class_attr = "I am a class attribute" # 类属性

# 通过类名修改类属性的值
MyClass.class_attr = "Modified class attribute"

# 输出修改后的类属性值
print(MyClass.class_attr) # 输出:"Modified class attribute"

# 创建实例对象
obj = MyClass()

# 通过实例对象修改类属性的值
obj.class_attr = "New class attribute value"

# 输出实例对象的属性值
print(obj.class_attr) # 输出:"New class attribute value"

# 输出类属性的值
print(MyClass.class_attr) # 输出:"Modified class attribute"

exercise2

1
2
2.定义学生类student,在该类中使用构造函数实现对学生信息(姓名、年龄、性别)
的初始化,然后针对类的各个属性建立相应的方法来获取属性的值

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
'''
2.定义学生类student,在该类中使用构造函数实现对学生信息(姓名、年龄、性别)
的初始化,然后针对类的各个属性建立相应的方法来获取属性的值
'''
class student():
name = ''
age = 0
sex = ''
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def get_name(self):
return self.name
def get_age(self):
return self.age
def get_sex(self):
return self.sex

studentA = student("xiaoming", 19, "男")

print(studentA.get_name())
print(studentA.get_age())
print(studentA.get_sex())

exercise3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
3.定义一个学生类。有下面的类属性:
1 姓名
2 年龄
3 成绩(语文,数学,英语)[每课成绩的类型为整数]
类方法:
1 获取学生的姓名:get_name() 返回类型:str
2 获取学生的年龄:get_age() 返回类型:int
3 返回3门科目中最高的分数。get_course() 返回类型:int
写好类以后,可以创建对象测试下:
stu = Student('zhangming',20,[69,88,100])
返回结果:
zhangming
20
100

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
"""
3.定义一个学生类。有下面的类属性:
1 姓名
2 年龄
3 成绩(语文,数学,英语)[每课成绩的类型为整数]
类方法:
1 获取学生的姓名:get_name() 返回类型:str
2 获取学生的年龄:get_age() 返回类型:int
3 返回3门科目中最高的分数。get_course() 返回类型:int
写好类以后,可以创建对象测试下:
stu = Student('zhangming',20,[69,88,100])
返回结果:
zhangming
20
100
"""
class Student:
def __init__(self, name, age, scores):
self.name = name
self.age = age
self.scores = scores

def get_name(self):
return self.name

def get_age(self):
return self.age

def get_course(self):
return max(self.scores)

# 创建学生对象并测试
stu = Student('zhangming', 20, [69, 88, 100])
print(stu.get_name())
print(stu.get_age())
print(stu.get_course())

exercise4

1
2
3
4.练习:
有一个学校,人数为0,入职的老师和学生,人数增加1,老师要显示姓名和工号,
学生要显示姓名和成绩,老师和学生入职后都需要做自我介绍

知识点

继承:teacher和student继承自people

通过修改__str__方法来打印信息

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
"""
4.练习:
有一个学校,人数为0,入职的老师和学生,人数增加1,老师要显示姓名和工号,
学生要显示姓名和成绩,老师和学生入职后都需要做自我介绍
"""
class people():
def __init__(self, name, id):
self.name = name
self.id = id
def introduction(self):
print(f"大家好,我是{self.name}")

class teacher(people):
def __init__(self, name, id):
super(teacher, self).__init__(name, id)
def __str__(self):
msg = f"姓名:{self.name} 工号:{self.id}"
return msg
class student(people):
def __init__(self, name, id, scores):
self.scores = scores
super(student, self).__init__(name, id)
def __str__(self):
msg = f"姓名:{self.name} 学号:{self.id} 成绩:{self.scores}"
return msg

class school():
def __init__(self):
self.total_num = 0
self.teachers = []
self.students = []
def add_teachers(self, teacher):
self.teachers.append(teacher)
self.total_num += 1
print(teacher)
teacher.introduction()
def add_student(self, student):
self.students.append(student)
self.total_num += 1
print(student)
student.introduction()

jinan_university = school()
teacherA = teacher("xiazhihua", "0001")
studentA = student("ztb", "123", [89, 89, 89])
jinan_university.add_teachers(teacherA)
jinan_university.add_student(studentA)

Abstract

以前方法存在的问题:

都只是为了捕获特定的伪造线索,比如噪声(noise patterns), 混合边界(blending boundaries)和频率(frequency artifacts),导致容易陷入局部最优,从而降低鲁棒性和泛化能力

创新点

提出CFM框架,原文which can be flexibly assembled with various backbones to boost their generalization and robustness performance,那么是一种模块吗?

CFM框架组成(先把原文放在这,看后面怎么说)

首先构建了一个细粒度的三元组,并通过先验知识不可知的数据增强来抑制特定的伪造痕迹

Specifically, we first build a fine-grained triplet and suppress specific forgery traces through prior knowledge-agnostic data augmentation

随后,我们提出了一个细粒度的关系学习原型,通过实例和局部相似感知损失来挖掘伪造中的关键信息

Subsequently, we propose a fine-grained relation learning prototype to mine critical information in forgeries through instance and local similarity-aware losses

此外,我们设计了一种新颖的渐进式学习控制器来引导模型专注于主要特征组件,使其能够以从粗到精的方式学习关键伪造特征

Moreover, we design a novel progressive learning controller to guide the model to focus on principal feature components, enabling it to learn critical forgery features in a coarse-to-fine manner

INTRODUCTION

研究背景:

以常见的4种伪造手段Deepfakes , Face2Face ,FaceSwap and NeuralTextures为代表的深度伪造技术不断发展,并且越来越多现成的伪造软件被开发被人利用,导致了严重的金融欺诈,假新闻和身份假冒。

早期检测

生物信息,比如眨眼,头部位置不一致和面部扭曲伪影,效果差

基于深度学习的检测,泛化性差

基于深度学习与捕获先验已知的特征,对图像失真的鲁棒性差

目标

抗过拟合的同时挖掘出尽可能多的伪造线索

实现

数据集准备

利用先验知识不可知的数据增强来防止模型陷入局部最优,并驱动模型学习更广义的伪造知识;

学习框架

引入细粒度三元关系学习方案,使模型能够学习更多的固有特征表示

正则化方案

用PLC正则化

目标函数

实例相似度感知损失和局部相似度感知损失来同时学习全局关键特征和局部细微伪影

基于EfficientNet-B4的不同线索提取器的注意图

上图每个部分图像第一列是不同形式伪造的图片

提取特征的主干网络都是EfficientNet-B4(可以换成线性transformer试试)

第二列是用普通卷积层提取出的基本伪造特征

第三列是用低频提取出的噪声线索

第四列是用本文提出的CFM框架提取出的关键伪造线索

a部分的图像并没有经过任何变换,b部分的图像经过了下采样,c部分的图像加入了高斯噪声,对比可以看出根据基础线索(估计即使边界)和根据频率线索的检测都受到了干扰

RELATED WORK

A. Prior Knowledge-Based Face Forgery Detection

缺点:抗扰动性差

B. Face Forgery Detection via Representation Learning

基础transformer讲解

Position Encoding

前面是没有考虑位置信息的,举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import torch
import torch.nn as nn


m = nn.MultiheadAttention(embed_dim=2, num_heads=1)
# embed_dim=2:指定了输入的嵌入维度(embedding dimension),即每个输入样本的特征维度为2,说白了就是图像的列数
# num_heads=1:指定了注意力头的数量,即将输入特征分成几份进行注意力计算。在这个例子中,只使用了1个注意力头。
t1 = [[[1., 2.], # q1, k1, v1
[2., 3.], # q2, k2, v2
[3., 4.]]] # q3, k3, v3

t2 = [[[1., 2.], # q1, k1, v1
[3., 4.], # q3, k3, v3
[2., 3.]]] # q2, k2, v2

q, k, v = torch.as_tensor(t1), torch.as_tensor(t1), torch.as_tensor(t1)
print("result1: \n", m(q, k, v))

q, k, v = torch.as_tensor(t2), torch.as_tensor(t2), torch.as_tensor(t2)
print("result2: \n", m(q, k, v))

输出结果

发现对b1没有影响

所以

Vision Transformer模型详解

参考文章一

参考文章二

题目

分析

这题最初的想法用dfs解决,但会超时,分析是因为每次递归计算的值没有利用,所以开一个dp[n][m][k]数组,表示从起点开始,在经过点(x, y),并且在使用喷气背包的次数为t的情况下,能否到达终点

另外要注意地图的边界是从1开始,不是从0开始

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
static int MAXSIZE = (int)1e3 + 3;
static int[][][] dp = new int[MAXSIZE][MAXSIZE][2];
// dp有三个值:-1表示没有遍历过,0表示从起点,经过点(x, y),在喷气背包使用t次的情况下无法抵达终点,1则相反,表示可以抵达
static int[][] map = new int[MAXSIZE][MAXSIZE];
static int sx, sy, fx, fy;
static int k;
static int n, m;
static int[] dx = {0, 1, 0, -1};
static int[] dy = {1, 0, -1, 0};
static boolean isValid(int x, int y) {
return x >= 1 && x <= n && y >= 1 && y <= m;
}
static int dfs(int x, int y, int p) {
// 如果发现已经抵达终点
if(x == fx && y == fy) {
return 1;
}
// 如果发现当前坐标位置已经遍历过,dp思想的核心体现
if(dp[x][y][p] != -1) {
return dp[x][y][p];
}
// 上下左右依次遍历
for(int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
// 判断移动后是否还在地图里
if(!isValid(nx, ny)) continue;
// 如果当前喷气背包没有使用
if(p == 0) {
// 当前高度比下一个高度高
if(map[x][y] >= map[nx][ny]) {
int canReach = dfs(nx, ny, 0);
// 如果经过当前点可以抵达终点
if(canReach == 1) {
// 将dp[x][y][p]置为1并且返回1,向上一层传递
dp[x][y][p] = 1;
return 1;
}
}
// 当前高度比下一个高度低但是使用喷气背包后可以抵达
if(map[x][y] < map[nx][ny] && map[x][y] + k >= map[nx][ny]) {
int canReach =dfs(nx, ny, 1);
if(canReach == 1) {
dp[x][y][p] = 1;
return 1;
}
}
} else { // 如果当前喷气背包已经使用
if(map[x][y] >= map[nx][ny]) {
int canReach = dfs(nx, ny, 1);
if(canReach == 1) {
dp[x][y][p] = 1;
return 1;
}
}
}
}
dp[x][y][p] = 0;
return 0;
}
static void fillArrays() {
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
for(int k = 0; k < 2; k++) {
dp[i][j][k] = -1;
}
}
}
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
n = scan.nextInt();
m = scan.nextInt();
k = scan.nextInt();
sx = scan.nextInt();
sy = scan.nextInt();
fx = scan.nextInt();
fy = scan.nextInt();
fillArrays();
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
map[i][j] = scan.nextInt();
}
}
if(dfs(sx, sy, 0) == 1) {
System.out.println("Yes");
} else {
System.out.println("No");
}
scan.close();
}
}

基本概念

核心思想

为了解决一个“大”问题,将“大”问题分解成两个“小”问题

举个例子:一次可以走一个台阶或者两个台阶,问走到第n个台阶时,一共有多少种走法?要走到第n级台阶,分成两种情况,一种是从n-1级台阶走一步过来,一种是从n-2级台阶走两步过来

状态

形如dp[i][j] = val的取值,其中i, j为下标,用于描述、确定状态所需的变量,val为状态值

状态转移

状态与状态之间的转移关系,转移方向决定了迭代或递归方向

常见特征:重叠子问题,最优子结构

重叠子问题:

斐波那契数为例,用递归计算fib(5),分解为图示的子问题,其中fib(3)计算了2次,其实只算1次就够了

最优子结构

两种编码方法

自顶向下与记忆化

先考虑大问题,再缩小到小问题,递归很直接地体现了这种思路。为避免递归时重复计算子问题,可以在子问题得到解决时,就保存结果,再次需要这个结果时,直接返回保存的结果就行了。这种存储已经解决的子问题的结果的技术称为“记忆化(Memoization)”。   以斐波那契数为例,记忆化代码如下:

1
2
3
4
5
6
7
int memoize[N];                                  //保存结果
int fib (int n){
if (n == 1 || n == 2) return 1;
if(memoize[n] != 0) return memoize[n]; //直接返回保存的结果,不再递归
memoize[n]= fib (n - 1) + fib (n - 2); //递归计算结果,并记忆
return memoize[n];
}

自下而上与制表递推

先解决子问题,再递推到大问题。通常通过填写表格来完成,编码时用若干for循环语句填表。根据表中的结果,逐步计算出大问题的解决方案。

用制表法计算斐波那契数,维护一个一维表dp[],记录自下而上的计算结果,更大的数是前面两个数的和。

1
2
3
4
5
6
7
const int N = 255;
int dp[N];
int fib (int n){
dp[1] = dp[2] =1;
for (int i=3;i<=n;i++) dp[i] = dp[i-1] +dp[i-2];
return dp[n];
}

分析步骤

确定状态

一般为“到第i个为止,方案数/最小代价/最大价值

确定状态转移方程

根据状态转移方向决定迭代还是递归

确定最终状态

题目一

题干

分析

状态:dp[i][j]表示第i行,第j列的和的最大值

状态迁移方程:方向从底向上,取当前位置的下一层的左边或右边的最大值与当前位置求和,作为当前位置dp值

最终状态:dp[1][1]

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.Scanner;

public class Main {
static int MAXSIZE = 105;
static int[][] dp = new int[MAXSIZE][MAXSIZE];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
// 读入三角形里面的数据
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= i; j++) {
dp[i][j] = scan.nextInt();
}
}
//
for(int i = n - 1; i >= 1; i--) {
for(int j = 1; j <= i; j++) {
// 状态转移方程,不过是从下往上
dp[i][j] += Math.max(dp[i + 1][j], dp[i + 1][j + 1]);
}
}
System.out.println(dp[1][1]);
scan.close();
}
}

题目二

题干

分析

确定状态:dp[i]表示到第i级台阶有多少种方案

确定状态转移方程:从后往前,dp[i] = dp[i - 1] + dp[i - 2]

确定最终状态:dp[N]

注意,题目中如果告诉你结果比较大,java一般需要开long

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import java.util.Scanner;

public class Main {
static int p = (int)1e9 + 7;
static int MAXSIZE = (int)10e5 + 5;
static boolean[] broken = new boolean[MAXSIZE];
static long[] dp = new long[MAXSIZE];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int N = scan.nextInt();
int M = scan.nextInt();
for(int i = 0; i < M; i++) {
int worse = scan.nextInt();
broken[worse] = true;
}
// 第0级台阶
broken[0] = false;
dp[0] = 1;
// 第一级台阶比较特殊,如果第一级台阶没有坏,则只用一种可能,就是从第0级台阶上来
if(broken[1] == false) dp[1] = 1;
for(int i = 2; i <= N; i++) {
if(broken[i] == false) {
dp[i] = (dp[i - 1] + dp[i - 2]) % p;
}
}
// for(int i = 1; i <= N; i++) {
// System.out.print(dp[i] + " ");
// }
// System.out.println();
System.out.println(dp[N]);
scan.close();
}
}

题目三

题干

分析

确定状态

dp[i]:最后一个桶放在位置i的方案总数

状态转移方程

因为dp[i]表示最后一个桶在位置i所具有的方案总数,而要求最近的相邻两个桶之间要相隔k个桶,所以dp[i]等于从最后一个桶在位置1的方案(dp[1])到最后一个桶在位置i - k - 1的方案数(dp[i - k - 1])的和,即\(dp[j] = \sum_{i = 1}^{j - k - 1}dp[i]\)

最终状态

题目要求的是总方案数,由dp数列定义可知不是dp[N],所以要对dp数组求前缀和,prefix[N]才是答案

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.Scanner;

public class Main {
static int p = (int)1e9 + 7;
static int N = (int)1e6 + 5;
static long[] dp = new long[N];
static long[] prefix = new long[N];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int k = scan.nextInt();
dp[0] = prefix[0] = 1;
for(int i = 1; i <= n; i++) {
if(i - k - 1 < 1) dp[i] = 1;
else dp[i] = prefix[i - k - 1];
prefix[i] = (prefix[i - 1] + dp[i]) % p;
}
System.out.println(prefix[n]);
scan.close();
}
}

入门一题