我的Python学习笔记_Day15 面向对象编程1
面向对象编程
图片来源于网络
面向过程编程(穷人) – 算法和逻辑
函数式编程(小资) – 函数
面向对象编程(富豪) – 类和对象
1. 类和对象
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'>
推荐阅读
-
我的Python学习笔记_Day15 面向对象编程1
-
Java的面向对象编程基本概念学习笔记整理
-
Java的面向对象编程基本概念学习笔记整理
-
阿里Java学习路线:阶段 1:Java语言基础-Java面向对象编程:第20章:接口的定义与使用:课时91:代理设计模式
-
阿里Java学习路线:阶段 1:Java语言基础-Java面向对象编程:第7章:数组的定义与使用:课时29:数组与方法
-
阿里Java学习路线:阶段 1:Java语言基础-Java面向对象编程:第7章:数组的定义与使用:课时26:数组引用传递分析
-
阿里Java学习路线:阶段 1:Java语言基础-Java面向对象编程:第7章:数组的定义与使用:课时34:对象数组
-
阿里Java学习路线:阶段 1:Java语言基础-Java面向对象编程:第30章:链表的定义与使用:课时139:根据索引取得数据
-
阿里Java学习路线:阶段 1:Java语言基础-Java面向对象编程:第27章:异常的捕获及处理:课时119:异常处理流程
-
阿里Java学习路线:阶段 1:Java语言基础-Java面向对象编程:第23章:包的定义及使用:课时104:生成jar文件