欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

我的Python学习笔记_Day15 面向对象编程1

程序员文章站 2024-03-22 08:01:39
...

面向对象编程

我的Python学习笔记_Day15 面向对象编程1
图片来源于网络

面向过程编程(穷人) – 算法和逻辑

函数式编程(小资) – 函数

面向对象编程(富豪) – 类和对象

1. 类和对象

1) 什么是类,什么是对象

类就是拥有相同功能和相同属性的对象的集合

对象就是类的实例

我的Python学习笔记_Day15 面向对象编程1

图片来源于网络

上图中,动物就是一个大类,狗和羊是继承动物类的子类,而你家的狗就是一个狗的实例,即对象。

2) 类的声明

用代码描述清楚这个类是那些相同的功能和相同属性的集合

class 类名:
	"""类的说明文档"""
	
	类的内容
写法 说明
class 声明类的关键字,固定写法
类名 自己命名
要求:标识符,不能是关键字
规范:见名知意,大驼峰式命名
类的说明文档 用""""""引起来的说明性文字
类的内容 用来描述共同的属性和功能
包含属性(声明在类中的变量)和方法(声明在类中的函数)
class Person:
    """人类"""

    def eat(self):
        print('人类吃饭')

    def sleep(self):
        print('人类睡觉')

    def thinking(self):
        print('人类思考')
3) 创建对象

类() – 创建类的对象并且返回

tom = Person()
jack = Person()

2. 对象方法

1) 类中的方法

类*同的功能

方法 – 声明在类中的函数

类中的方法分为三种:对象方法、类方法、静态方法

2) 对象方法

a. 怎么声明:直接声明在类中的函数

b. 怎么调用:用对象调用;以对象.对象方法()的形式调用

c. 特点:自带参数self,参数self通过对象调用的时候不用传参,系统会自动给self传参,传的是当前实例(对象)
self又叫当前对象,谁调用就是谁
对象能做的事,self都能做

class Dog:
    def eat(self, food):
        """这里的eat就是对象方法"""
        print('狗吃' + food)
dog1 = Dog()
dog1.eat('骨头')  # 狗吃骨头
class Dog:
    def eat(self, food):
        """这里的eat就是对象方法"""
        print('狗吃' + food)
        self.run()

    def run(self):
        print('狗跑步')


dog1 = Dog()
dog1.eat('shit')
# 结果:
# 狗吃shit
# 狗跑步

3. init方法和构造方法

1) 构造函数

在python中声明类的时候,系统会自动声明一个和类同名的函数(构造函数),用来创建当前类的对象。
当我们调用构造函数创建对象的时候,系统会自动调用类中的__init__方法来初始化对象

2) __init__方法

ps:前后都有__的方法叫魔法方法,绝大部分是系统自动写好的

__init__是魔法方法中比较特殊的,需要开发者自己声明,声明的时候函数名必须是__init__,并且保证这个方法是对象方法
声明后不需要手动调用,创建对象时系统会自动调用

class Person:
    def __init__(self, name, age):
        print('init方法{}{}'.format(name, age))


p1 = Person('tom', 18)
p2 = Person('jack', 20)
# 结果:
# init方法tom18
# init方法jack20

切记:
a. 创建对象的时候系统会自动调用__init__方法
b. 创建对象的时候,构造函数需不需要参数、需要几个参数看__init__方法除了self之外还有几个参数

4. 类中的属性

即类中保存数据的变量,分为两种:字段、对象属性

1) 字段

a. 怎么声明

​ 直接声明在类里面、函数外面的变量

b. 怎么使用

​ 通过类使用,以类.字段的形式取使用

c. 什么时候用

​ 不会因为对象不同而不一样的属性就声明成字段

class Person:
    a = 10  # 这个a就是字段


print(Person.a)  # 10
2) 对象属性

a. 怎么声明

​ 声明在__init__方法中;以self.属性名=值的形式来声明

b. 怎么使用

​ 通过对象来使用,以对象.属性的形式来使用

c. 什么时候用

​ 会因为对象不同而不一样的属性就声明成对象属性

class Person:

    def __init__(self, name, age):
        # 这里self.name和self.age都是对象属性
        self.name = name
        self.age = age


p1 = Person('小明', 18)
print(p1.name, p1.age)  # 小明 18

5. 类中的方法

对象方法、类方法、静态方法

1) 对象方法

a. 怎么声明

​ 直接声明在类中的函数

b. 怎么调用

​ 通过对象来调用

c. 特点

​ 自带一个参数self;self在调用的时候不用传参,指向当前对象

d. 什么时候用

​ 对初学者:如果实现函数的功能需要用到对象属性,这个函数就声明成对象方法(需要用到self时)

2) 类方法

a. 怎么声明

​ 在函数声明前加@classmethod

b. 怎么调用

​ 通过类调用,类.类方法

c. 特点

​ 自带一个参数cls;cls在调用的时候不用传参,系统自动将当前类传给cls
​ 当前类能做的事情,cls都可以做

d. 什么时候用

​ 对初学者:如果实现函数的功能不需要用到对象属性的前提下,需要类的时候,用类方法

3) 静态方法

a. 怎么声明

​ 在函数声明前加@staticmethod

b. 怎么调用

​ 通过类调用,类.静态方法

c. 特点

​ 没有自带的参数

d. 什么时候用

​ 对初学者:如果实现函数的功能不需要用到对象属性的前提下,也不需要类的时候,用静态方法

class Student:

    num = 100  # 类的字段

    def __init__(self, name, tel, age=18):
        self.name = name
        self.age = age
        self.tel = tel

    def study(self):
        """这个方法是对象方法"""
        print('%s在学习' % self.name)

    @classmethod
    def func1(cls):
        """这个方法是类方法"""
        print('类方法func1')

        stu2 = cls('小红', '119', 20)
        stu2.study()
        print(stu2.num)

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


stu = Student('小明', '110')
stu.study()

Student.func1()

Student.func2()

# 结果:
# 小明在学习
# 类方法func1
# 小红在学习
# 100
# 静态方法func2

坑:

注意:理论上类中的所有方法都可以通过对象或者类调用,但是没意义

class Keng:
    num = 100

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

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

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


# 用类调用对象方法
Keng.func1(123)  # self会失去意义

k = Keng()

# 用对象调用类方法
k.func2()  # 和类调用的效果一模一样,cls参数依然是当前类,不是对象,但是多此一举

# 用对象调用静态方法
k.func3()  # 没意义

6. 对象属性的增删改查

先创建一个类和两个实例:

class Person:

    def __init__(self, name, age=18, gender='女'):
        self.name = name
        self.age = age
        self.gender = gender


p1 = Person('小明', gender='男')
p2 = Person('小红', 20)
1) 获取属性值

a. 对象.属性 - 获取对象指定属性的值,若不存在则报错

b. getattr(对象, 属性名: str) - 获取对象指定属性的值,若不存在则报错

c. getattr(对象, 属性名: str, 默认值) - 获取对象指定属性的值,若属性不存在,返回默认值

print(p1.name)
print(getattr(p1, 'name'))
print(getattr(p1, 'name', '无名氏'))
print(getattr(p1, 'aaaa', '无名氏'))

结果:

小明
小明
小明
无名氏

点语法和getattr的区别在于:属性的提供方法不同
点语法后面必须跟存在的属性,而getattr()可以用变量来提供

2) 修改属性和增加属性

a. 对象.属性 = 值 - 当属性存在的时候就是修改,不存在是就是增加

b. setattr(对象, 属性名, 值) - 当属性存在的时候就是修改,不存在是就是增加

p1.age = 10
p1.height = 180
print(p1.age, p1.height)  # 10 180
3) 删除对象属性

a. del 对象.属性 - 删除对象中指定的属性

b. delattr(对象, 属性名)

del p1.name
print(p1.name)  # 报错,p1没有age属性
delattr(p1, 'age')
print(p1.age)  # 报错,p1没有age属性

注意:

属性的增删改查只针对指定对象有效,不会影响别的对象

7. 内置类属性

在声明类的时候,系统自动创建的属性

常用内置类属性:

先创建类

class Dog:
    """狗类!"""
    num = 100
    
    def __init__(self, name, age=3, gender='公狗'):
        self.name = name
        self.age = age
        self.gender = gender
        
    def func1(self):
        print('对象方法', self.name)
        
    @classmethod
    def func2(cls):
        print('类方法')
    
    @staticmethod
    def func3():
        print('静态方法')
    

dog1 = Dog('大黄')
1) 类.__name__

类的字段,获取类的名字

print(Dog.__name__)  # Dog
print(type(Dog.__name__))  # <class 'str'>
2) 对象.__class__

对象属性,获取当前对象的类(和type(对象)功能一样)

print(dog1.__class__)  # <class '__main__.Dog'>
print(type(dog1.__class__))  # <class 'type'>
3) 类.__doc__

获取类的说明文档

print(Dog.__doc__)  # 狗类!
print(type(Dog.__doc__))  # <class 'str'>
4) 类.__dict__

获取类中所有的字段和字段对应的值,以字典的形式返回

print(Dog.__dict__)  # {'__module__': '__main__', '__doc__': '狗类!', 'num': 100, '__init__': <function Dog.__init__ at 0x00000000027B71F8>, 'func1': <function Dog.func1 at 0x00000000027B7798>, 'func2': <classmethod object at 0x00000000027CB908>, 'func3': <staticmethod object at 0x00000000027CB948>, '__dict__': <attribute '__dict__' of 'Dog' objects>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>}
print(type(Dog.__dict__))  # <class 'mappingproxy'>
5) 对象.__dict__

获取对象所有的属性和对应的值,以字典的形式返回

print(dog1.__dict__)  # {'age': 3, 'gender': '公狗', 'name': '大黄'}
print(type(dog1.__dict__))  # <class 'dict'>

ps:

魔法属性__slots__:

用来约束当前类最多能够拥有的对象属性

但是,一旦设置了__slots__就无法使用对象.__dict__

例子:

class Dog:
    """狗类!"""
    num = 100

    __slots__ = ('name', 'age', 'gender', 'height', 'weight')

    def __init__(self, name, age=3, gender='公狗'):
        self.name = name
        self.age = age
        self.gender = gender

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

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

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


dog1 = Dog('大黄')
print(dog1.__dict__)  # AttributeError: 'Dog' object has no attribute '__dict__'
6) 类.__module__

获取指定类声明所在的模块,返回的是模块名

print(Dog.__module__)  # __main__
print(type(Dog.__module__))  # <class 'str'>
7) 类.__bases__

获取指定类的所有父类,返回的是一个元组

print(Dog.__bases__)  # (<class 'object'>,)
print(type(Dog.__bases__))  # <class 'tuple'>