实例属性和类属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/python3
# -*- coding: utf-8 -*-


class Student:
name = 'globe_name'

def __init__(self):
self.name = 'name'


s1 = Student()
print(s1.name) # name 实例属性优先级更高,先找实例属性,没有才会找类属性

  • 调用属性会先找实例属性,没有再找类属性
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
class Student:
# 类属性
count = 0

def __init__(self, name) -> None:
# 实例属性
self.name = name
Student.count += 1


for i in range(10):
s = Student(i)
print('name : {}, count : {}'.format(s.name, s.count)) # 这里使用s.count和Student.count是一样的

# 打印结果
name : 0, count : 1
name : 1, count : 2
name : 2, count : 3
name : 3, count : 4
name : 4, count : 5
name : 5, count : 6
name : 6, count : 7
name : 7, count : 8
name : 8, count : 9
name : 9, count : 10

  • 类属性是类绑定,实例之间共享,也就是会存在安全性问题

实例方法、类方法、静态方法

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
COUNT = 1


class Student:
name = 'globe_name'

def instence_foo(self):
print('instence_foo')

@classmethod
def class_foo(cls):
print('class_foo')

@staticmethod
def static_foo():
print('static_foo')


s1 = Student()
s1.instence_foo()
print('s1.instence_foo : {}'.format(s1.instence_foo))

s1.class_foo()
print('s1.class_foo : {}'.format(s1.class_foo))

Student.class_foo()
print('Student.class_foo : {}'.format(Student.class_foo))

s1.static_foo()
print('s1.static_foo : {}'.format(s1.static_foo))

Student.static_foo()
print('Student.static_foo : {}'.format(Student.static_foo))

# 输出结果
instence_foo
s1.instence_foo : <bound method Student.instence_foo of <__main__.Student object at 0x10d0ef340>>
class_foo
s1.class_foo : <bound method Student.class_foo of <class '__main__.Student'>>
class_foo
Student.class_foo : <bound method Student.class_foo of <class '__main__.Student'>>
static_foo
s1.static_foo : <function Student.static_foo at 0x10d161040>
static_foo
Student.static_foo : <function Student.static_foo at 0x10d161040>
  • 实例方法只能被实例对象调用
  • 类方法和静态方法都可以被实例对象或者类名调用
  • 实例方法被绑定到实例对象上,类对象被绑定到类上,静态方法是独立的,只是被写入了class中,其实python和Java不同,完全可以写到class外也可以被调用(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
COUNT = 1

class Student:
name = 'globe_name'

def __init__(self):
self.age = 100

def instence_foo(self):
print('instence_foo')
print('get COUNT : {}'.format(COUNT))
print('get name : {}'.format(self.name))
print('get age : {}'.format(self.age))

@classmethod
def class_test(cls):
print('class_test')

@classmethod
def class_foo(cls):
print('class_foo')
print('get COUNT : {}'.format(COUNT))
print('get name : {}'.format(cls.name))
cls.class_test()
# print('get age : {}'.format(cls.age)) # AttributeError: type object 'Student' has no attribute 'age'

@staticmethod
def static_foo():
print('static_foo')
print('get COUNT : {}'.format(COUNT))


s1 = Student()
s1.static_foo()
s1.class_foo()
s1.static_foo()

# 输出
static_foo
get COUNT : 1
class_foo
get COUNT : 1
get name : globe_name
class_test
static_foo
get COUNT : 1
  • 本质上,实例对象被创建后会被赋值给self,所以可以通过self关键字调用对象资源
  • 而类资源被赋值给了cls,所以可以通过cls访问到类资源(属性和方法),但是不能访问到实例资源(这些资源是在对象创建的时候被初始化的)
  • 静态方法就不说了,啥都访问不到,只有外面的公共资源可以访问
  • Java里面没有类资源这个层级,只有静态和实例,类名被使用的时候静态资源就被创建了(因为静态资源可以通过类名直接调用),别的都是实例资源在对象被创建后才可以使用
  • ==放在类定义以外的资源是如何中内存中存活和销毁的呢?==