python类与对象(一)

文章发布时间:

最后更新时间:

文章总字数:
1.4k

预计阅读时间:
6 分钟

  类比对象大,对象是类底下的一个实例,这些对象都有一些共同特征,因此归为一类。

一.类

类定义了对象的属性(特征)和方法(功能)。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 创建一个类,其中有属性和方法(函数)
class Arknights:
atk = None
fangyu = None
zudang = None
cost = None
def op():
print('攻击')

print(type(Arknights))

# 顺带一提,List也是一个类,同理其他数据也是
print(type(list))

输出:

1
2
<class 'type'>
<class 'type'>

二.对象

2.1 创建对象并访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 创建一个类的对象
class Arknights:
atk = None
fangyu = None
zudang = None
cost = None
def op():
print('攻击')

Ace = Arknights()
print(type(Ace))

# 访问属性
print(Ace.atk)
print(Ace.fangyu)
print(Ace.zudang)
print(Ace.cost)

# 访问方法,隐式操作,op()会将创建的‘对象’当作参数传入即op(Ace)
Ace.op()

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<class '__main__.Arknights'>
None
None
None
None

---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[16], line 20
17 print(Ace.cost)
19 # 访问方法,隐式操作,op()会将创建的对象当作参数传入即op(Ace)
---> 20 Ace.op()

TypeError: Arknights.op() takes 0 positional arguments but 1 was given

正确做法:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 创建一个类的对象
class Arknights:
atk = None
fangyu = None
zudang = None
cost = None
def op(self):
print('攻击')

Ace = Arknights()
print(type(Ace))

Ace.op()

输出:

1
2
<class '__main__.Arknights'>
攻击

2.2 两个同类对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 创建一个类
class Arknights:
atk = None
fangyu = None
zudang = None
cost = None
def op():
print('攻击')

# 俩对象属性方法一样
Ace = Arknights()
Ew = Arknights()

# 地址不一样
print(id(Ace))
print(id(Ew))

输出:

1
2
1683888245072
1683888245408

2.3 创建对象时初始化成员值

1
2
3
4
5
6
7
8
9
10
class Arknights:
# 这个函数是官方初始函数,会在对象创建时直接调用,将对象传给self,后面分别取值
# 里面的self可以改,不过一般都写self
def __init__(self,atk,fangyu,zudang,cost):
print(atk,fangyu,zudang,cost)


Ace = Arknights(100,100,1,8)
# 此时是不能访问atk的,因为atk是初始化的值,不是对象的属性,还没有赋值给对象
print(Ace.atk)

输出:

1
2
3
4
5
6
7
8
9
10
11
100 100 1 8
<__main__.Arknights object at 0x000001880F8D0C20>

---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[31], line 10
8 Ace = Arknights(100,100,1,8)
9 print(Ace)
---> 10 print(Ace.atk)

AttributeError: 'Arknights' object has no attribute 'atk'

正确做法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 正确做法
class Arknights:
def __init__(self,atk,fangyu,zudang,cost):
# 这里将初始化的值赋值给新建的属性给对象
self.Atk = atk
self.Fangyu = fangyu
self.Zudang = zudang
self.Cost = cost

Ace = Arknights(100,100,1,8)
print(Ace.Atk)
print(Ace.Fangyu)
print(Ace.Zudang)
print(Ace.Cost)

输出:

1
2
3
4
100
100
1
8

2.4 既有创建时就相同的值,也可以初始化一些属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Arknights:
life = 1
def __init__(self,atk,fangyu,zudang,cost):
# 这里将初始化的值赋值给新建的属性给对象
self.Atk = atk
self.Fangyu = fangyu
self.Zudang = zudang
self.Cost = cost

Ace = Arknights(111,55,2,8)
ew = Arknights(100,50,1,20)

# 两者的life值相同
print(Ace.life)
print(Ace.Atk)

print()

print(ew.life)
print(ew.Atk)

print()

输出:

1
2
3
4
5
6
7
8
1
111

1
100

2
1

2.5 更改对象属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Arknights:
life = 1
def __init__(self,atk,fangyu,zudang,cost):
# 这里将初始化的值赋值给新建的属性给对象
self.Atk = atk
self.Fangyu = fangyu
self.Zudang = zudang
self.Cost = cost
def change_life(self,num):
self.life = num

Ace = Arknights(111,55,2,8)
ew = Arknights(100,50,1,20)

# 直接对象访问
Ace.life = 2
print(Ace.life)
print(ew.life)

# 通过类内部函数访问,隐式操作change_life(Ace,3)
Ace.change_life(3)
print(Ace.life)

输出:

1
2
3
2
1
3

注意,没有对象的话是不能直接访问属性的,不要跟函数包含函数搞混了。

1
2
3
4
5
6
7
8
class Arknights:
life = 1
def fun(self,x):
if x == life:
print('你死了')

a = Arknights()
a.fun(1)

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[53], line 9
6 print('你死了')
8 a = Arknights()
----> 9 a.fun(1)

Cell In[53], line 5, in Arknights.fun(self, x)
4 def fun(self,x):
----> 5 if x == life:
6 print('你死了')

NameError: name 'life' is not defined

正确做法:

1
2
3
4
5
6
7
8
class Arknights:
life = 1
def fun(self,x):
if x == self.life:
print('你死了')

a = Arknights()
a.fun(1)

输出:

1
你死了

2.6 共享方法

有一个有趣的问题,既然创建多个对象,里面的属性和方法都一样,那python的设计者有没有必要将每个对象里都放一次方法呢?

答案是否定的,他们都有相同的属性,但共享方法,方法是单独放在一个空间里的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Arknights:
life = 1
def __init__(self,atk,fangyu,zudang,cost):
self.Atk = atk
self.Fangyu = fangyu
self.Zudang = zudang
self.Cost = cost
def change_life(self,num):
self.life = num

Ace = Arknights(111,55,2,8)
ew = Arknights(100,50,1,20)

# 看看地址怎么样
print(id(Ace.change_life),id(ew.change_life))

输出:

1
1683892761472 1683892761472

结果就是俩函数地址一样,也就是方法的位置是固定的,是共享的。

—————————————————————————————————————————————————————————————————————————

然后我们来看看方法的使用,类中方法中也可以访问另一个方法,用self来访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Arknights:

def fn(self,x):
print('fn')
# 用self调用
self.fn1(x)

# 也可以传入上一个函数的参数哦
def fn1(self,y):
print(y)
print('fn1')

Ace = Arknights()
Ace.fn(1)

输出:

1
2
3
fn
1
fn1

三.类属性

就是一个类共同的属性,是在一开始就决定好的东西。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class arknights:
x = 1
def fun(self):
print('fun')

a = arknights()


# 也可以通过类来访问类属性
print(arknights.x)
print(a.x)

# 也可以通过类来访问其中的方法,但这不是类方法
a.fun()
arknights.fun()

输出:

1
2
3
4
5
6
7
8
9
10
11
12
1
1
fun

---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[56], line 15
13 # 也可以通过类来访问其中的方法,但这不是类方法
14 a.fun()
---> 15 arknights.fun()

TypeError: arknights.fun() missing 1 required positional argument: 'self'

正确做法:

1
arknights.fun(123)

输出:

1
fun

注意:这里的123才是传进去的self参数,直接用类来调用其中的方法是不可行的,一般传的都是类自己,比如这里可以是arknights.fun(arknights)。