Day 15 方法和类
几点总结
- 数据持久化,将数据以文件的形式保存在硬盘中
- 以b的方式打开文件时,encoding 不能赋值,b表示
- with open() as xxx: 可以在缩进中操作文件,结束缩进文件自动关闭
- exit()退出程序
- 在编程和设计中,需要特别考虑数据的成长性
面向对象编程
- 面向过程编程: 遇到问题,解决问题的采用具体的逻辑和步骤,越编越难
- 函数式编程 : 遇到问题,在编程过程中将各个功能分解成具体的函数,通向康庄大道
- 面向对象编程 : 遇到问题,解决问题的方式是,采用工具,利用工具,现有的东西来解决问题
几个重要定义
-
类就是具有相同功能或者相同属性的对象的集合
-
对象就是类的实例,每个人都是人这个类的对象,对象是通过类来创建的
-
定义类:用代码来描述你的这个类是拥有哪些相同功能(函数),和哪些相同属性(变量)的对象的集合
""" 语法: class 类名: 类的说明文档 类的内容(包含方法和属性) 1) 说明 a class - 关键字;固定写法 b 类名 - 由程序员自己命名:两个要求,三个规范,采用驼峰式命名,而且是大驼峰,第一个单词首字母大写 c 说明文档 - 多行注释,对类进行说明 d 类的内容 - 包含定义在类中的函数(方法)和定义在类中的变量(属性) 方法包括:对象方法,类方法,静态方法 属性包括:类属性,对象属性 user_name - PEP8 userName - 大驼峰 UserName - 大驼峰 """
三种方法
- 定义在类中的函数就是方法
"""
1)对象方法
怎么定义: 直接定义在类中的函数就是对象方法
怎么调用 : 以对象.xxx()的形式来调用
特点: 自带参数self,调用函数时,self不需要传参,系统自动将当前对象传给self(谁调用,self指向谁)
除了self 还可以有其他参数,用法和常规函数一样
2)类方法
怎么定义: 定义函数签,添加装饰器,@classmethod
怎么调用 : 以 类名.xxx() 调用
特点:自带参数cls,调用函数的时候cls不需要传参,
3)静态方法
怎么定义 : @staticmethod 后面
怎么调用: 类名.xxx()
特点: 没有特点
"""
class A:
# func1是对象方法
def func1(self):
print(self)
print("对象方法")
def func2(self,a,b = 10):
print(f"打印一些数字, a= {a},b = {b}")
@classmethod
def func3(cls): # 装饰器,可以有自己的参数
print(cls)
print("类方法")
@staticmethod
def func4():# 默认没有参数,可以自己加
print("静态方法")
a1 = A() # 创建对象
a1.func1() # 调用对象方法
print(a1) # <__main__.A object at 0x0000025341171F70> 表示A类里面的一个对象,后者是地址
a1.func2(100,300) # 给对象函数传入参数
A.func3() # 调用类方法
A.func4() # 调用静态方法
print(A) #<class '__main__.A'>
类的初始化
-
__init__
魔法函数__init__ 如果在类中添加了__init__方法,那么在创建当前类的对象的时候就会自动调用 创建对象的时候需不需要实参,需要几个实参由类中的__init__决定 创建对象传入实参
-
__repr__
魔法函数__repr__ : 打印类的对象的时候,会自动使用这个方法,并且将这个方法对应的返回值作为打印结果作为返回值 返回值必须是字符串 修改对象打印值
class B: def __init__(self, m, n): print("init方法被调用", m + n) def __repr__(self): return f"<B的对象,在{id(self)}>" b1 = B(10, 30) #init方法被调用 40 在创建对象时就会执行 print(b1) # <B的对象,在1568910454496> 修改创建对象的打印值
两种属性
-
类属性
定义,创建: 直接在类中定义的变量就是类属性 怎么使用 : 在类的外面使用,以 类名.xxx使用 什么时候用: 对象在变,属性不变 圆周率
-
对象属性
怎么定义 : 以 slfe.属性名 =属性值 的形式 定义在__init__方法中 怎么使用 : 以 对象.xxx 的方式去使用 什么时候用: 针对每一个具体的对象 对象改变,属性也变
class A: name = "张三" # 可以理解为类变量,其可以在任何对象和函数中使用,表述为这个类中所有的对象具有的公共属性 def __init__(self): # 创建对象属性,其中每个对象可以通过__init__()传入实参,对具体对象进行描述 self.x = 10 self.y = 20 a1 = A() #调用类属性,变量 print(a1.y) # 调用具体对象变量
父子关系
-
儿子只能继承父亲的财产,父亲不能抢夺儿子媳妇
-
注意: 定义类的时候没有写父类,那么这个类会默认继承 object(基类),祖先
__init__ 需要注意 优先用自己的 没有再找父类 再找父类的父类 调用父类的__init__ super().__init__() 添加对象属性
class A(): pi = 3.141592653 def __init__(self, name,age = 18): self.name = name self.age = age def func1(self,age): print("这个是对象方法.",self.name,age,A.pi) def func123(self): print("这个是对象方法.", self.name, self.age, A.pi) @classmethod def func2(cls): print("这个是类方法",A.pi) @staticmethod def func3(): print("这个是静态方法") a1 = A("王八") a1.func123() A.func2() """ 每一个对象方法,可以使用类属性和对象属性,以及自己传入的实参,但不能使用别的对象方法的实参 对象属性,可以在任何一个对象方法中使用,但不能在类方法和静态方法使用 类属性,才能在类方法和静态方法使用 """
class B(A): pi2 = 82751376220 def __init__(self, age): self.age = age def func11(self): print("这个是B中的对象方法") @classmethod def func22(cls): print("这个是B中的类方法") @staticmethod def func33(): print("这个是B中的静态方法") """ 在B中重新定义对象属性后,原父亲对象属性不能使用 所有需要用到父类对象属性的方法不能用 """
```python class A(): pi = 3.141592653 def __init__(self, name, age=18): self.name = name self.age = age def func1(self, age): print("这个是对象方法.", self.name, age, A.pi) def func123(self): print("这个是对象方法.", self.name, self.age, A.pi) @classmethod def func2(cls): print("这个是类方法", A.pi) @staticmethod def func3(): print("这个是静态方法") a1 = A("王八") a1.func123() A.func2() class B(A): pi2 = 82751376220 def __init__(self, gender): self.gender = gender super(A,self).__init__() # super方法,这里传入的是父亲 def func11(self): print("这个是B中的对象方法") @classmethod def func22(cls): print("这个是B中的类方法") @staticmethod def func33(): print("这个是B中的静态方法") b1 = B(gender="男") #创建对象时,只能首先传入儿子的参数 b1.name = "旺财"# 父亲的参数用 对象.属性 赋值 b1.age = 20 b1.func11() b1.func1(18) """ 创建对象时,只能首先传入儿子的参数 父亲的参数用 对象.属性 赋值 注意各种参数的位置关系 """ ```
作业
-
定义一个矩形类,拥有属性:长、宽 拥有方法:求周长、求面积
class Rectangle(): def __init__(self, length, width, ): self.length = length self.width = width def perimeter(self): return 2 * (self.length + self.width) def area(self): return self.length * self.width R1 = Rectangle(10, 20) print(R1.perimeter()) print(R1.area())
-
定义一个二维点类,拥有属性:x坐标、y坐标 拥有方法:求当前点到另外一个点的距离
class TwoPoints(): def __init__(self, point1: tuple, point2: tuple): self.point1 = point1 self.point2 = point2 def distance(self): result = ((self.point1[0] - self.point2[0]) ** 2 + (self.point1[-1] - self.point2[-1]) ** 2) ** 0.5 return f"{result :.2f}" t2 = TwoPoints((1, 1), (2, 2)) print(t2.distance())
-
定义一个圆类,拥有属性:半径、圆心 拥有方法:求圆的周长和面积、判断当前圆和另一个圆是否外切
class Circle(): pi = 3.14 def __init__(self, r1, point1: tuple): self.r1 = r1 self.point1 = point1 def perimeter(self): C = 2 * Circle.pi * self.r1 return f"{C:.2f}" def area(self): S = Circle.pi * self.r1 ** 2 return f"{S:.2f}" def tangency(self, r2, point2: tuple): distance = ((self.point1[0] - point2[0]) ** 2 + (self.point1[-1] - point2[-1]) ** 2) ** 0.5 length = self.r1 + r2 if distance == length: return "相切" else: return "不相切" R1 = Circle(5, (2, 5)) # 周长 print(R1.perimeter()) # 面积 print(R1.area()) # 判断是否相切 print(R1.tangency(5, (-2, 5)))
-
定义一个线段类,拥有属性:起点和终点, 拥有方法:获取线段的长度
class Segment(): def __init__(self, point1: tuple, point2: tuple): self.point1 = point1 self.point2 = point2 def length(self): result = ((self.point1[0] - self.point2[0]) ** 2 + (self.point1[-1] - self.point2[-1]) ** 2) ** 0.5 return f"{result:.2f}" A = Segment((1, 3), (2, 4)) print(A.length())