2021.5.19面向对象
类和对象
1.定义类(创建类)
定义类用代码描述清楚这个类是拥有哪些相同功能哪些相同属性的对象的集合。
功能- 对应的是函数
属性 - 保存数据的变量(在类中叫属性)
语法:
class 类名:
类的说明文档
类的内容
说明:
class - 关键字,固定写法
类名 - 程序员自己命名
要求:是表示符,不是关键字
规范:见名知义;驼峰式命名(单词之间采用首字母大写),首字母大写;不使用系统函数名、模块名、类名。
: - 固定写法
类的说明文档 - 本质就是多行注释
类的内容 - 包括属性和方法。属性分为:类属性(类的字段)和对象属
方法分为:对象方法、类方法和静态方法
注:方法就是定义在类中的函数
2.定义对象(创建对象)
对象方法
1.方法
定义在类中函数就是方法
2.对象方法
怎么定义: 直接定义在类中的函数(定义函数前不用加装饰器)
怎么调用: 用对象来调用 - 对象.函数名()
特点: 自带参数self,在调用的时候self不用传参,系统会自动将当前对象传给self(谁调用self指向谁)
class Person:
"""人类"""
def sleep(self):
# self=p2
print(f'self:{self}')
print('睡觉')
def eat(self, food):
print(f'吃{food}')
p1 = Person() # 创建对象
p2 = Person()
print(f'p1:{p1}, p2:{p2}')
p2.sleep()
# p1.sleep(100) # TypeError: sleep() takes 1 positional argument but 2 were given
p1.eat('面条')
p2.eat('小龙虾')
构造方法和初始化方法
1.构造函数/构造方法
函数名和类名相同,并且是用来创建对象的方法就是构造方法。
Python的构造函数在创建的类的时候由系统自动创建,程序员只需要在创建对象的自动调用
2.初始化方法: init
定义类的时候可以根据需求在类中添加对象方法: init,添加的时候要保证函数名是__init__,第一个参数是self。
除此以外我们可以随意添加参数和函数体。
每次使用类创建对象的时候,系统会自动调用这个类中的__init__方法
调用构造方法创建对象的时候需不需要参数,需要几个参数看这个类的__init__方法除了self以外有没有额外的参数。
魔法方法:类中,方法名由__开头并且以__结尾的方法就是魔法方法。所有的魔法方法都是自动调用。
class Dog:
def __init__(self):
print('__init__被调用')
下面的这个函数的定义由系统自动完成
def Dog():
新建好的对象 = 创建对象并且申请内存保存对象
新建好的对象.init()
return 新建好的对象
class Cat:
def __init__(self, name, age):
print('猫:__init__被调用')
print(f'name:{name}, age:{age}')
cat1 = Cat('小花', 3)
cat2 = Cat(name='土豆', age=2)
cat3 = Cat('美女', age=1)
属性
1.属性
属性是用来描述类的数据特征。属性的本质是保存数据的变量。
2.对象属性和类属性
1)类属性
怎么定义:直接定义在类中的变量就是类属性
怎么使用:通过类来使用, 类.类属性
什么时候用:属性的值不会因为对象不同而不一样,这种属性就定义成类属性
2)对象属性
怎么定义:以 ‘self.属性名=值’ 的形式定义在__init__方法中
怎么使用:通过对象来使用,对象.对象属性
什么时候用:属性的值会因为对象不同而不一样,这种属性就定义成对象属性
class Person:
# num是类属性
num = 61
# name、age、gender是对象属性
def __init__(self):
self.name = '小明'
self.age = 18
self.gender = '男'
print(Person.num)
Person.num = 60
print(Person.num)
p1 = Person()
print(p1.name, p1.age, p1.gender)
p1.name = '小胡'
print(p1.name)
p2 = Person()
class Circle:
pi = 3.1415926
3.对象属性赋初值的三种方式
方式1: 赋一个固定的值
方式2:使用没有默认值的参数赋值
方式3:使用有默认值的参数赋值
class Dog:
def __init__(self, name, color, breed='土狗', gender='母'):
self.breed = breed
self.name = name
self.gender = gender
self.color = color
self.age = 1 # 赋固定值
# __repr__方法在当前类的对象被打印的时候会被自动调用,这个方法的返回值(必须是字符串)是什么就打印什么。
def __repr__(self):
# 打印谁,self就是谁
# return f'{self.name, self.breed, self.gender, self.color, self.age}'
return f'<{str(self.__dict__)[1:-1]}>'
dog1 = Dog('财财', '黄色')
print(f'dog1:{dog1}')
dog2 = Dog('花花', '白色', gender='公')
print(f'dog2:{dog2}')
练习:定义一个商品类,拥有属性:价格、名称、产地、类型、生产日期、保质期
# 要求:创建对象的时候价格、名称、生产日期必须赋值; 其他属性可以赋值也可以不赋值,产地默认温州、保质期默认1年、类型默认是食品
# 打印对象的时候打印商品基本信息
class Goods:
def __init__(self, name, price, p_date, address='温州', expiration_date='1年', type='食品'):
self.price = price
self.name = name
self.address = address
self.type = type
self.produced_date = p_date
self.expiration_date = expiration_date
def __repr__(self):
return f'<{str(self.__dict__)[1:-1]}>'
g1 = Goods('泡面', 3, '2021-3-24')
print(g1)
方法
- 对象方法
怎么定义:直接在类中定义函数(函数前不加装饰器)
怎么调用:对象.对象方法()
特点:自带参数self, self不用传参,谁调用self就指向谁。
什么时候用:如果实现函数的功能需要用到对象,一定是对象方法 - 类方法
怎么定义:在定义函数前加装饰器@classmethod
怎么调用:类.类方法()
特点:自带参数cls,cls不用传参,系统将当前类传个cls (谁调用就指向谁)
什么时候用:实现函数的功能,在不需要对象属性的时候需要类就使用类方法 - 静态方法
怎么定义:在定义函数前加装饰器@staticmethod
怎么调用:类.静态方法
特点:没有默认参数
什么时候用:实现函数的功能既不需要当前类的对象也不需要当前类,就使用静态方法
class Test:
def func1(self):
print('对象方法')
@classmethod
def func2(cls):
# cls = Test
print(f'cls: {cls}')
print('类方法')
@staticmethod
def func3():
print('静态方法')
t1 = Test()
# 用对象调用对象方法
t1.func1()
# 用类调用类方法
Test.func2()
print(f'Test:{Test}')
class Circle:
pi = 3.1415926
def __init__(self, radius):
self.radius = radius
def area(self):
return self.radius ** 2 * Circle.pi
@classmethod
def set_pi(cls, value):
cls.pi = value
c1 = Circle(1)
c2 = Circle(10)
print(c1.area())
print(c2.area())
作业
-
定义一个狗类和一个人类:
狗拥有属性:姓名、性别和品种 拥有方法:叫唤
人类拥有属性:姓名、年龄、狗 拥有方法:遛狗
class Dog: def __init__(self,name,gender,breed): self.name=name self.gender=gender self.breed=breed def __repr__(self): return f'<{str(self.__dict__)[1:-1]}>' def call(self): return '叫唤' dog1 = Dog('二胖','公狗','拉布拉多') print(f'dog1:{dog1}') print(dog1.call()) class Person: def __init__(self,name,age,dog): self.name=name self.age=age self.dog=dog def __repr__(self): return f'<{str(self.__dict__)[1:-1]}>' def took(self): return '遛狗' person1 = Person('小小',18,'拉布拉多') print(f'person1:{person1}{person1.took()}')
-
定义一个矩形类,拥有属性:长、宽 拥有方法:求周长、求面积
class Square: def __init__(self, long,wide): self.long = long self.wide = wide def perimeter(self): return (self.long+self.wide) * 2 def dimension(self): return self.long * self.wide a1 = Square(5, 10) print(a1.perimeter()) print(a1.dimension())
-
定义一个二维点类,拥有属性:x坐标、y坐标 拥有方法:求当前点到另外一个点的距离
class Two_dimensional: def __init__(self,x1,y1): self.x1 = x1 self.y1 = y1 def distance(self,x2,y2): return ((x2-self.x1)**2+(y2-self.y1)**2)**0.5 spot=Two_dimensional(2,8) print(spot.distance(2,4))
-
定义一个圆类,拥有属性:半径、圆心 拥有方法:求圆的周长和面积、判断当前圆和另一个圆是否外切
class Circle: pi = 3.1415926 def __init__(self,radius,x1,y1): self.radius=radius self.x1=x1 self.y1=y1 def perimeter(self): return 2 * self.radius * Circle.pi def area(self): return self.radius ** 2 * Circle.pi def combination(self,new_radius,x2,y2): if self.radius+new_radius==((x2-self.x1)**2+(y2-self.y1)**2)**0.5: return '当前圆和另一个圆是外切' else: return '当前圆和另一个圆不是外切' a1=Circle(5,2,8) print(a1.perimeter()) print(a1.area()) print(a1.combination(8,1,10))
-
定义一个线段类,拥有属性:起点和终点, 拥有方法:获取线段的长度
class Lines: def __init__(self,origin,terminus): self.origin=origin self.terminus=terminus def get_long(self): return self.terminus-self.origin a1=Lines(5,10) print(a1.get_long())