根据面对问题不同人呈现出来的思维模式不同,可以将编程思维分为三种:
面相过程编程(穷人思想) — 遇到问题马上想到解决这个问题的具体逻辑和步骤
函数式编程(小资思想) — 遇到问题马上想到有没有一个已经存在的函数可以解决这个问题,如果没有,自己造一个
面向对象编程(富豪思想) — 遇到问题马上想到有没有一个具有这个功能的对象,如果没有就造对象
一个函数只具备一个功能。
一个对象可以同时具有多个功能。(一个对象可以绑定多个函数,还可以保存多个数据)
类就是拥有相同功能或者相同属性的对象的集合
对象就是类的实例
例如:如果人是类,则每一个人都是人的对象,余老师是对象,我是另一个对象
杯子是类,则我的紫色保温杯是杯子的对象, 我的矮的玻璃杯是杯子的另一个对象
斗地主游戏是类,则每一盘已经开启的游戏这个活动都是斗地主游戏的对象
类是一个抽象的概念,而对象是一个能用的具体的表现
定义类:用代码来描述你这个类是拥有那些相同功能(一个功能就用一个函数描述)和哪些相同属性(属性用变量保存)的对象的集合。
类名后也可以加一个括号:
class 类名(父类):
类的说明文档
类的内容(包含方法(功能)和属性)
说明:
a. class — 关键字;固定写法
b. 类名 — 由程序员自己命名
两要求:是标识符;不是关键字
规范:见名知义; 不使用系统的函数名、类名、模块名; 采用驼峰式命名(必须是大驼峰),所有单词首字母大写
c. 类的说明文档 — 本质就是一个多行注释
d. 类的内容 — 包含定义在类中的函数(方法)和定义在类中的变量(属性)
方法包括:对象方法、类方法、静态方法
属性包括:类属性、对象属性
# user_name --- PEP8
# userName --- 小驼峰
# UserName --- 大驼峰
对象是通过类来创建的
语法:类名()
dog1 = Dog()
dog2 = Dog()
print(dog1, dog2)
# <__main__.Dog object at 0x0000016FAAA6F220> <__main__.Dog object at 0x0000016FAAA6F190>
# at 后面是地址,若地址不同,则数据是不同的数据
定义在类中的函数就是方法
对象方法:直接定义在类中的函数就是对象方法
类方法:在定义的函数前加装饰器 @classmethod
静态方法:在定义的函数前加装饰器 @staticmethod
使用:类名.xxx
特点:没有特点
一个装饰器只管一个函数,如果需要多个类方法,需要在每个类方法的前面都加上装饰器
如果在类中定义的方法需要用到类中的对象属性,则用对象方法;
如果在类中定义的方法需要用到类中的类属性,则用类方法;
如果在类中定义的方法需要用到类中的对象属性和类属性则用对象方法
如果在类中定义的方法不需要用到任何属性,则用静态方法
class A:
# 对象方法
def func1(self):
print(f'self: {self}')
print('对象方法')
def func2(self,a):
print(f'self: {self}')
print('对象方法')
# 类方法
@classmethod
def func3(cls):
print('类方法')
# 静态方法
@staticmethod
def func4():
print('静态方法')
# ---- ---- ---- 对象方法 ---- ----- ------ ------ ----- |
# 调用:对象.xxx() 需要先创建对象:对象=类名()
a1 = A()
# print(a1)
a1.func1() # 此时self = a1
a2 = A()
a2.func1() # 此时self = a2
# 发现系统会自动给self传参,且传的参self与a1的地址相同(即是同一个值)
# 调用对象时不用传参,系统会将当前调用的对象作为实参传给self
b1 = A()
b1.func2(10) # 对象方法 10 100
# ----- ---- ----- ----- 类方法 ----- ----
A.func3()
# ----- ---- ------- --- 静态方法 -- ---- --
A.func4()
# 例如数学类没有对象,但有很多数学相关的方法,可以用静态方法
# 即是本身和类没有说明关系,但为了让方法更有归属感而这样定义类
魔法方法的特点:
a. 函数名以 __开头,并且以__结尾
b. 魔法方法不需要程序员自己调用,系统会在特定情况下自动调用
2) 两个常见的魔法方法
a. __init__
如果在类中添加了__init__方法,那么在创建当前类的对象时会自动调用这个方法
创建对象的时候需不需要实参,需要几个实参,由类中的__init__决定
# 用于 创建对象属性
b. __repr__
在类中添加了这个方法,则最后返回什么,打印对象时就输出什么(必须是字符串类型)
如果类中添加了__repr__方法,打印类的对象时会自动调用这个方法,并将这个方法的返回值作为打印结果打印
在类中添加__repr__方法的时候, 这个方法必须是字符串。
class A:
def __init__(self): # 可以自己添加形参
print('init被调用')
def __repr__(self):
return 'abc'
a1 = A()
a2 = A()
print(a1) # abc
class B:
def __init__(self, m, n):
print(f'm:{m},n:{n}')
b1 = B(10, 3) # m:10,n:3
如果对打印结果不满意,可以用repr修改打印结果
class Student:
def __init__(self,name, age=18,gender='男'):
self.name=name
self.age = age
self.gender = gender
stu1 = Student('小明')
stu2 = Student('小花', age = 17, gender = '女')
print(stu1) # <__main__.Student object at 0x000002863A47B400>
print(stu2) # <__main__.Student object at 0x000002863A47B2B0>
# ------------------ 添加__repr__后 -----------------------
class Students:
def __init__(self, name, age=18, gender='男'):
self.name = name
self.age = age
self.gender = gender
def __repr__(self):
return f'姓名:{self.name},年龄:{self.age}, 性别:{self.gender}'
stus1 = Students('小明')
stus2 = Students('小花', age=17, gender='女')
print(stus1) # 姓名:小明,年龄:18, 性别:男
print(stus2) # 姓名:小花,年龄:17, 性别:女
类属性
直接定义在类中的变量就是类属性
类名.xxx
如果属性的值不会因对象不同而不同,就用类属性。例如圆周率,所以圆的圆周率都相同
对象属性
以’self.属性名 = 属性值’ 的形式定义在_ init __的方法中
对象.xxx 使用前须先创建对象
如果属性的值会因对象的不同而不同则用对象属性
class A:
# 类属性
a = 10
name = '张三'
# x、n 是对象属性
def __init__(self):
self.x = 100
self.n = 'hello!'
# 使用类属性:类名.xxx
print(A.a) # 10
print(A.name) # 张三
# 使用对象属性:
a1 = A()
print(a1.x) # 100
print(a1.n) # hello!
class Circle:
# 所以圆的圆周率都一样,所以用类属性
pi = 3.1415926
def __init__(self, r=0):
self.r = r
# 圆的半径会因圆不同而不同,所以用对象属性
# 如果对象方法中需要用到对象属性,由self作为对象来提供
# 如果需要的数据或变量,类中没有则需要增加形参
def area(self):
# 圆面积
return Circle.pi * self.r ** 2
def perimeter(self):
# 圆周长
return Circle.pi * self.r * 2
对象属性赋值方法:
class Dog:
def __init__(self, name, gender, breed, age=3):
# self.name = '财财' # 赋一个固定的值, 会导致创建的狗都叫财财
self.name = name # 在创建时给形参,这样名字可以在函数外给
self.age = age # 可以在创建时给形参并赋默认值
self.gender = gender
self.breed = breed
# 赋一个固定的值,则每次都需要改名
# dog1 = Dog()
# dog1.name = '小黑'
dog1 = Dog('小黑','男', '土狗')
print(dog1.name) # 小黑
继承:让子类直接拥有父类的属性和方法
子类 — 继承者
父类 — 被继承的类
语法
class 类名(父类1,父类2……):
类的说明文档‘
类的内容
注意:如果定义类的时候没有写父类,那么这个类会默认继承 object(基类)
子类调用原理: 先看子类本身有没有调用的方法或属性,
没有就查父类,还没有查父类的父类,直到查到object还没有就报错
父类只能用其本身的内容
子类能用其父类、父类的父类、……、object(基类)以及其自身的内容
super().__ init _ _() — 调用当前类的父类的__init__(),解决父类对象属性在子类中不能使用的问题
class A:
m = 100
def __init__(self):
self.n = 200
def func1(self):
print('对象方法')
@classmethod
def func2(cls):
print('类方法')
@staticmethod
def func3():
print('静态方法')
# B 继承 A 的一切
class B(A):
# 添加新的内容
x = 'hello'
# z在子类中添加新的对象属性会导致从父类继承的对象属性不能使用
def __init__(self):
super().__init__() # 调用当前类的父类的__init__(),解决父类对象属性在子类中不能使用的问题
# super(B,self).__init__()
self.y = 130
# 添加新的方法
def func4(self):
print('新的对象方法')
@classmethod
def func5(cls):
print('新的类方法')
@staticmethod
def func6():
print('新的静态方法')
# B 能用 所继承类的所有内容
print(B.m) # 100
b1 = B()
print(b1.n) # 200
b1.func3() # 静态方法
b1.func2() # 类方法
b1.func1() # 对象方法
# B 能用 自己独有的新添加的所有内容、
print(B.x) # hello
print(b1.y) # 130
b1.func4() # 新的对象方法
b1.func5() # 新的类方法
b1.func6() # 新的静态方法