天天看点

day17 面向对象及作业day17 面向对象

day17 面向对象

一、类和对象

1.定义类

定义类用代码描述清楚你这个类是拥有哪些相同功能哪些相同属性的对象的集合。

功能 - 对应的是函数

属性 - 保存数据的变量(在类中叫属性)

语法:

class 类名:

类的说明文档

类的内容

说明:

class - 关键字,固定写法

类名 - 程序员自己命名

要求:是标识符,不是关键字

规范:见名知义;驼峰式命名(第二个单词开始,单词之间采用首字母大写),首字母大写;不使用系统函数名、类名、模块名

: - 固定写法

类的说明文档 - 本质就是多行注释

类的内容 - 包括属性和方法

属性分为:类属性(类的字段)和对象属性

方法分为:对象方法、类方法和静态方法

注解:方法就是定义在类中的函数

class Students:
    """
    学生类
    """
    pass
           

2.定义对象(创建对象)

语法:类()

stu1 = Students()
stu2 = Students()
print(stu1, stu2)
           

二、对象方法

1.方法

定义在类中的函数就是方法

2.对象方法

怎么定义:直接定义在类中的函数(定义函数前不用加装饰器)

怎么调用:用对象来调用 - 对象.函数名()

特点:自带参数self,在调用的时候self不用传参,系统会自动将当前对

class Person:
    """
    人类
    """
    def sleep(self):
        print(f'self:{self}')
        print('睡觉')

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


p1 = Person()   # 创建对象
p2 = Person()
print(f'p1:{p1} p2:{p2}')
p1.sleep()


p1.eat('面条')
           

三、构造方法和初始化方法

1.构造函数/构造方法

函数名和类名相同,并且是用来创建对象的方法就是构造方法

Python的构造函数在创建类的时候由系统自动创建,程序员只需要在创建对象的时候自动调用

2.初始化方法:_init_

定义类的时候可以根据需求在类中添加对象方法:init,添加的时候要保证函数名是__init__,第一个参数是self。

除此以外我们可以随意添加参数和函数体。

使用类创建对象的时候,系统会自动调用这个类中的__init__方法

调用构造方法创建对象的时候需不需要参数,需要几个参数看这个类的__init__方法除了self以外有没有额外的参数

魔法方法:类中,方法名由__开头并且以__结尾的方法就是魔法方法。所有的魔法方法都是自动调用。

class Dog:
    def __init__(self):
        print('__init__被调用')
           

下面的这个函数的定义由系统自动完成

def Dog():

新建好的对象 = 创建对象并且申请内存保存对象

新建好的对象.init()

return 新建好的对象

dog1 = Dog()  # 没有调用__init__,就打印了,说明只要一创建对象,__init__就被调用
dog2 = Dog()
           
class Cat:
    def __init__(self, name, age):
        print('猫:__init__被调用')
        print(f'name:{name}, age:{age}')


cat1 = Cat('小花', 3)
cat2 = Cat(name='土豆', age=2)
           

=====补充:=

def __init__(x, y):
    print('自己的__init__被调用')
    print(f'x:{x},y:{y}')


def Cat(*args, **kwargs):
    print(f'=={kwargs}')   # kwargs:{'x': 10, 'y': 20}
    __init__(*args, **kwargs)
    print(f'args:{args}')
    print(f'kwargs:{kwargs}')   # kwargs:{'x': 10, 'y': 20}


c1 = Cat(10, 20)
c2 = Cat(x= 10, y=20)

*x, y = 10, 20, 30, 40  # *的打包功能


def func2(a, b, c):
    print(f'a:{a}, b:{b}, c:{c}')


func2(100, 200, 300)
print('====')
alist = (100, 200, 300)
print(*alist)   # *的解包功能
print('====')
func2(*alist)   # func2(100, 200, 300)

dict1 = {'a': 10, 'b': 20, 'c': 30}
# print(**dict1)
# **dict1 => a= 10, b=20,c=30
func2(**dict1)   # func2(a=10, b=20, c=30)
           

四、属性

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)


class Circle:
    # pi就是类属性
    pi = 3.1415926

           

3.对象属性赋初值的三种方式

方式1:赋一个固定的值,

方式2:使用没有默认值的参数赋值

方式3:使用有默认值的参数赋值

class Dog:
    def __init__(self, name, color, breed='土狗', gender='母'):
        self.breed = breed  # 方式3
        self.name = name  # 方式2
        self.gender = gender # 方式3
        self.color = color  # 方式2
        self.age = 1   # 方式1

    # __repr__方法在当前类的对象被打印的时候会被自动调用,这个方法的返回值(必须是字符串)是什么就打印什么
    def __repr__(self):
        # 打印谁,self就是谁
        # return f'{self.name, self.breed, self.gender, self.color, self.age}'
        return str(self.__dict__)

dog1 = Dog('财财', '黄色')
print(f'dog1:{dog1}')    # dog1:abc

dog2 = Dog('花花', '白色', gender='公')
print(f'dog2:{dog2}')
           

练习:定义一个商品类,拥有属性:价格、名称、产地、类型、生产日期、保质期

要求:创建对象的时候价格、名称、生产日期必须赋值、产地默认温州、保质期默认1年、类型默认食品

打印对象的时候打印商品所有的基本信息

class Goods:
    def __init__(self, price, name, date, place='温州', expiration_date='1年', goods_type='food'):
        self.price = price
        self.name = name
        self.date = date
        self.place = place
        self.expiration_date = expiration_date
        self.goods_type = goods_type

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


goods1 = Goods('100元', 'xx', '2021.2.1')
print(goods1)

           

五、方法

1.对象方法

怎么定义:直接在类中定义函数(函数前不加装饰器)

怎么调用:对象.对象方法()

特点:自带参数self,self不用传参,谁调用self就指向谁

什么时候用:如果实现函数的功能需要用到对象属性,一定是对象方法

2.类方法

怎么定义:在定义函数前加装饰器@classmethod

怎么调用:类.类方法()

特点:自带参数cls,cls不用传参,系统将当前类传给cls(谁调用就指向谁)

什么时候用:实现函数的功能,在不需要对象属性的时候需要类就使用类方法

3.静态方法:

怎么定义:在定义函数前装装饰器@staticmethod

怎么调用:类.静态方法

特点:没有默认参数

什么时候用:实现函数的功能既不需要当前类的对象也不需要当前类,就使用静态方法

class Test:

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

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

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


t1 = Test()

# 用对象调用对象方法
t1.func1()

# 用类调用类方法
Test.func2()


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
           

六、作业

  1. 定义一个狗类和一个人类:

    狗拥有属性:姓名、性别和品种 拥有方法:叫唤

    人类拥有属性:姓名、年龄、狗 拥有方法:遛狗

    class Dog:
    
        def __init__(self, name, gender, breed):
            self.name = name
            self.gender = gender
            self.breed = breed
    
        def bark(self):
            return '汪汪'
    
    
    class Person:
    
        def __init__(self, name, age, dog=None):
            self.name = name
            self.age = age
            self.dog = dog
    
        def walk_dog(self):
            print(f'{self.dog.name},叫一个:{self.dog.bark()}')
    
    
    p1 = Person('小明', '18')
    p1.dog = Dog('旺财', '母', '土狗')
    p1.walk_dog()  
               
  2. 定义一个矩形类,拥有属性:长、宽 拥有方法:求周长、求面积
    class Rectangle:
        def __init__(self, length, width):
            self.length = length
            self.width = width
    
        def perimeter(self):
            return (self.length + self.width) * 2
    
        def area(self):
            return self.length * self.width
    
    
    r1 = Rectangle(3, 4)
    print(r1.perimeter())
    print(r1.area())
               
  3. 定义一个二维点类,拥有属性:x坐标、y坐标 拥有方法:求当前点到另外一个点的距离
    class TwoDimensionalPoint:
        def __init__(self, x, y):
            self.x = x
            self.y = y
    
        def coordinate(self):
            return self.x, self.y
    
    
    def distance(coordinate1:tuple, coordinate2:tuple):
        return ((coordinate1[0] - coordinate2[0]) ** 2 + (coordinate1[1] - coordinate2[1]) ** 2) ** 0.5
    
    
    d1 = TwoDimensionalPoint(1, 2)
    d2 = TwoDimensionalPoint(3, 2)
    print(distance(d1.coordinate(), d2.coordinate()))
               
  4. 定义一个圆类,拥有属性:半径、圆心 拥有方法:求圆的周长和面积、判断当前圆和另一个圆是否外切
    class Circle:
        pi = 3.14
    
        def __init__(self, radius, center=(0, 0)):
            self.radius = radius
            self.center = center
    
        def perimeter(self):
            return 2 * Circle.pi * self.radius
    
        def area(self):
            return Circle.pi * self.radius ** 2
    
    
    def isexcircle(radius1, radius2, center1:tuple, center2:tuple):
        if ((center1[0] - center2[0])**2 + (center1[1] - center2[1])**2) ** 0.5 == radius1 + radius2:
            print('两圆相切')
        else:
            print('两圆不相切')
    
    
    c1 = Circle(2, center=(1, 2))
    c2 = Circle(3, center=(2, 1))
    print(c1.perimeter(), c1.area())
    print(c2.perimeter(), c2.area())
    
    isexcircle(c1.radius, c2.radius, c1.center, c2.center)
               
  5. 定义一个线段类,拥有属性:起点和终点, 拥有方法:获取线段的长度
    class Line:
        def __init__(self, start_point:tuple, end_point:tuple):
            self.start_point = start_point
            self.end_point = end_point
    
        def length(self):
            return ((self.start_point[0] - self.end_point[0]) ** 2 + (self.start_point[1] - self.end_point[1]) ** 2) ** 0.5
    
    
    d1 = Line((2, 3), (3, 2))
    print(d1.length())