函数对象的操作

对象属性的增删改查

1
2
3
4
5
6
7
8
9
10
11
12
13
class Students:
def __init__(self,name,age,score):
self.name = name
self.age = age
self.score = score

# 在当前类的对象被打印的时候自动调用,并将这个方法的返回值作为打印结果(返回值必须是字符串)
def __repr__(self):
return str(self.__dict__)
# __dict__ 直接返回当前对象的所有属性和值,以字典的键值对的形式提供

stu1 = Students('小明',18,90)
stu2 = Students('张三',19,80)

1.查 - 获取属性值

1
2
3
1)对象.属性 - 获取对象指定属性的值(属性不存在报错)
2)getattr(对象,属性名) - 获取对象指定属性的值(属性不存在报错)
2)getattr(对象,属性名,默认值) - 获取对象指定属性的值(属性不存在,返回默认值)
1
2
3
4
5
6
print(stu1.name)
print(getattr(stu1,'name'))

# print(stu1.gender) # AttributeError: 'Student' object has no attribute 'gender'
# print(getattr(stu1,'gender')) # AttributeError: 'Student' object has no attribute ' gender '
print(getattr(stu1,'gender', '男')) #男

2.增,改

1
2
1)对象.属性 = 值 - 当属性存在时修改属性的值,属性不存在时候添加属性并赋值
2)setattr(对象,属性名,值) - 当属性存在时修改属性的值,属性不存在时候添加属性并赋值
1
2
3
4
5
6
stu1.name = "小黄"
print(stu1,stu2,sep='\n')

stu1.sex = "男"
stu2.sex = "女"
print(stu1,stu2,sep='\n')

3. 删

1
2
3
1)del 对象.属性 - 删除指定对象的指定属性
2)del 对象 - 删除指定对象
3)delattr(对象,属性名) - 删除指定对象的指定属性
1
2
3
del stu1.score
del stu2.score
print(stu1,stu2,sep='\n')

slots # 约束当前类可以拥有的对象属性

1
2
3
4
5
6
7
8
9
class A:
# __slots__ 属性值就是当前类的对象最多能够拥有的对象属性,为空的时候,这个类不能有对象属性
__slots__ = ('x','y','z') # 约束当前类可以拥有的对象属性

# 如果当前类使用了__slots__,那么这个类的对象就不能在使用__dict__属性

def __init__(self,x,y):
self.x = x
self.y = y

类属性

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
## 1. 类.__doc__  - 获取类的说明文档

print(int.__doc__)
print(int(10).bit_length()) # 获取对象的二进制位数
# print(dict.__doc__)

## 2.类.__module__ - 获取类所在的模块(类属性)

print(int.__module__)

## 3.对象.__class__ - 获取对象的类型,功能和type(对象)一样

class A:
pass

a = A()
print(a.__class__)
print(type(a))

## 4.1 类.__dict__ - 获取类所有的类属性和对应的值,以字典的形式返回
## 4.2 对象.__dict__ - 获取对象所有的对象属性和对应的值,以字典的形式返回

print(A.__dict__)
print(a.__dict__)

## 5. 类.__name__ - 获取类的名字(类属性)

print(A.__name__)

## 6.1 __base__ - 获取当前类的父类
## 6.2 __bases__ - 获取当前类的所有父类

print(A.__base__)

运算符重载

1
2
3
4
5
6
7
8
9
10
11
12
from copy import copy

print(10 + 29)
print('abc' + '34')
print([10, 34] + [239, 0, 'abc'])

print(10 - 9)
print({23, 89} - {23})


# 10 + 29 == 10.__add__(29)
# 'abc' + '34' == 'abc'.__add__('34')

1. python中的运算符

1
2
python中每个运算符都对应一个固定的魔法方法,哪个类型中实现的对应的魔法方法,那个类型的数据就支持对应的运算符。
(python中某种数据是否支持某种运算符就看这个类中是否定义了运算符对应的魔法方法)
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
class Student:
def __init__(self, name, age):
self.name = name
self.age = age

# self + other
def __add__(self, other):
return self.age + other.age

# self * other
def __mul__(self, other):
return [copy(self) for _ in range(other)]

# self > other
def __gt__(self, other):
return self.age > other.age

def __repr__(self):
return f'<{str(self.__dict__)[1:-1]}, id: {id(self)}>'
# return str(self.__dict__)


stu1 = Student('小明', 18)
stu2 = Student('小花', 20)

a = stu1 + stu2 # a = stu1.__add__(stu2)
print(a)
print(stu1 * 4)

# print(stu1 in stu2)

stu_list = [stu1, stu2, Student('张三', 12)]
print(stu_list)

# print(max(stu_list, key=lambda item: item.age))
print(max(stu_list))

1. 继承

1
2
3
继承就是让子类直接拥有父类的属性和方法。
子类 - 继承者
父类 - 被继承者,又叫超类

2. 继承的语法

1
2
3
4
5
6
7
8
9
10
11
class 类名(父类):
说明文档
类的内容


class 类名(父类1, 父类2,...):
说明文档
类的内容

注意:如果定义类的时候没有写继承关系,那么这个类默认继承基类object
class 类名: == class 类名(object):

3.添加新属性和方法

1
2
3
4
1)添加方法和添加类属性
直接在子类中定义新的类属性和方法

2)添加对象属性
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
class Person:
num = 61

def __init__(self):
self.name = '张三'
self.age = 30
self.gender = '男'

def eat(self, food):
print(f'在吃{food}')

@staticmethod
def func1():
print('静态方法')


class Student(Person):
x = '学生'

def __init__(self):
# 调用当前类的父类的__init__方法
super().__init__()
self.study_id = '0001'
self.subject = 'Python'

def study(self):
print('好好学习,天天向上!')

@classmethod
def func2(cls):
print('学生的类方法')


stu = Student()
print(stu.name, stu.age, stu.gender)
stu.eat('包子')

print(Student.num)
Student.func1()

print(Student.x)
stu.study()
Student.func2()
print(stu.study_id, stu.subject)


class A:
def __init__(self, x, y):
self.x = x
self.y = y


class B(A):
def __init__(self, m, n, x=10, y=20):
super().__init__(x, y)
self.m = m
self.n = n


a = A(200, 300)

b = B(1, 2)
print(b.x, b.y)
# b.x = 3
# b.y = 4

1. 子类和父类有相同的方法(重写)

1
2
3
4
5
6
7
8
9
10
11
12
class A:
def func1(self):
print('A的func1')


class B(A):
def func1(self):
print('B的func1')


B().func1()
A().func1()

2. super的用法

1
2
super(类, 对象).方法()   -  调用指定类的父类的指定方法
注意:()中的对象必须是()里面类的对象
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
class A:
def func1(self):
print('A的func1')


class B(A):
def func2(self):
super(B, self).func1()
print('B的func2')


B().func2()


print('-------------------------------------------------')
class A:
def func1(self):
print('A的func1')

def func2(self):
print('A的func2')


class B(A):
def func1(self):
print('B的func1')


class C:
def func1(self):
print('C的func1')


class D(C):
def func1(self):
super(B, B()).func2()
print('D的func1')


d = D()
d.func1()

3.多继承: 子类只能继承第一个父类的对象属性(方法和类属性都可以继承)

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
class AA:
num = 100

def __init__(self):
self.x = 100
self.y = 200

def func1(self):
print('对象方法AA')


class BB:
message = '你好'

def __init__(self):
self.m = 100
self.n = 200

def func2(self):
print('对象方法BB')


class CC(AA, BB):
pass


c = CC()

print(CC.num, CC.message)

c.func1()
c.func2()

print(c.x, c.y)
# print(c.m, c.n) # AttributeError: 'CC' object has no attribute 'm'

4. 私有化

1
2
3
4
5
6
7
8
9
10
访问权限(属性和方法的权限):公开的、保护的、私有的
公开的 - 在类的外部可以使用、类的内部可以使用、也可以被继承
保护的 - 在类的外部不可以使用、类的内部可以使用、也可以被继承
私有的 - 只能在类的内部使用,不能被继承,也不能在外部使用

python中类的内容的权限只有一种:公开的
python的私有化: 想让属性和方法变成私有的只需要在名字前加__(但是不能同时用__结尾)
python私有化的本质:就存储数据的时候在私有化名字前加 '_类名'

python中的保护:在名字前加_
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class A:
m = 100
__n = 200

@staticmethod
def func1():
print(A.m, A.__n)
A.__func2()

@staticmethod
def __func2():
print('私有方法')


print(A.m)
A.func1()

# print(A.__n)
# A.__func2()

print(A._A__n)
# python之禅

1. 拷贝

1
2
3
4
5
6
7
8
9
10
1)直接赋值
直接将变量中的地址赋值给另外一个变量,赋值后两个变量指向同一块内存区域,并且相互影响

2)浅拷贝
列表切片、列表.copy()、字典.copy()等都是浅拷贝、copy()
复制原数据产生一个新的数据,将新的数据的地址返回。如果原数据中有子对象(有可变数据),不会复制子对象

3)深拷贝
deepcopy
复制原数据产生一个新的数据,将新的数据的地址返回。如果原数据中有子对象,子对象也会被复制
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
from copy import copy,deepcopy
class Dog:
def __init__(self, name, gender='公'):
self.name = name
self.gender = gender

def __repr__(self):
return str(self.__dict__)


class Person:
def __init__(self, name, age=18, dog=None):
self.name = name
self.age = age
self.dog = dog

def __repr__(self):
return str(self.__dict__)


p1 = Person('小明', dog=Dog('财财'))
p2 = p1
p3 = copy(p1)
p4 = deepcopy(p1)

print(f'p1:{p1}, id:{id(p1)}')
print(f'p2:{p2}, id:{id(p2)}')
print(f'p3:{p3}, id:{id(p3)}')
print(f'p4:{p4}, id:{id(p4)}')
print('-------------------------------------------------')
p1.name = '小花'
p1.dog.name = '大黄'
print(f'p1:{p1}, id:{id(p1)}')
print(f'p2:{p2}, id:{id(p2)}')
print(f'p3:{p3}, id:{id(p3)}')
print(f'p4:{p4}, id:{id(p4)}')

2. 内存管理

1
2
3
4
5
6
7
1)内存的申请
定义变量保存数据的时候系统会自动申请。如果定义变量保存的时候可变数据,每次都会申请新的内存,如果是不可变的数据,会检查这个数据
是否已经保存过,如果已经存储就不会再重新申请内存。

2)释放
如果一个数据的引用计数(引用的个数)为0,那么这个数据就会被自动释放。
引用:保存数据地址的对象就是这个数据的引用