面向对象的程序设计与Python生态
文章目录
一、概念
-
类(class):对具有相同属性和方法的一组对象的描述或定义
-
数据类型:
- 不同的数据类型属于不同的类
- 使用内置函数查看数据类型
-
print(type(10)) # <calss,'int'>
-
对象:类的实例,如100、99都是 int 类之下包含的相似的不同个例
-
实例:含义与对象相同。
创建一个新对象的过程称为实例化,创建的具体对象称为这个类的实例。
二、类和对象
1.类的创建
类的命名规范:类名由一个或多个英文单词组成,每个英文单词首字母要大写,其余小写。
- 创建
class Student: # Student为类的名称,
pass
-
父类和子类
子类继承父类的所有属性
class School: School_name='HHU' def xiaoxun(): print('艰苦朴素,实事求是,严格要求,勇于探索') #创建子类: class 子类名(父类名) class Student(School): native_pace='吉林' #子类的运用 stu1=Student() print(stu1.School_name) # HHU stu1.xiaoxun() #艰苦朴素,实事求是,严格要求,勇于探索
2.类的组成
解惑:属性=变量、方法=函数
-
实例属性:是类的对象中的变量(需要赋给的值)
-
类属性:写在类中的变量(相当于默认值)
-
方法 定义 初始化方法 获得实例属性的方法(用法参考下方代码) 实例方法 一个操作函数(在类里面叫方法,在类外面叫函数) 类方法 使用@classmethod修饰的方法,使用类名直接访问的 静态方法 使用@staticmethod修饰的方法,使用类名直接访问的
class Student:
#类属性:直接写在类里的变量
native_pace='吉林'
#初始化方法
def __init__(self,name,age): #注意:方法名左右各两个下划线
self.name=name #self.name称为实例属性,将局部变量name的值赋给实例属性
self.age=age
#实例方法
def eat(self): #self必须有
print(self.name+'在吃饭...')
#静态方法
@staticmethod
def method():
print('我是静态方法')
#类方法
@classmethod
def cm(cls):
print('我是类方法')
3.类的对象的创建
***续接 2.2中的的代码***
stu1=Student('张三',20) # stu1就是Student类的一个对象
4.类的使用
-
类属性的使用方法
***续接 2.2中的代码*** stu1=Student('张三',20) stu2=Student('李四',30) print(stu1.native_pace) #吉林 print(stu1.native_pace) #吉林 #全部修改: 类名.类属性=x Student.native_pace='天津' print(stu1.native_pace) #天津 print(stu1.native_pace) #天津 #局部修改: 对象名.类属性=x stu1.native_pace='天津' print(stu1.native_pace) #天津 print(stu2.native_pace) #吉林
-
实例方法的调用
调用实例方法必须已经创建了对象
***续接 2.2中的代码*** #方法1: stu1.eat() # 对象名.方法名() print(stu1.name) #方法2: Student.eat(stu1) # 类名.方法名(对象名)stu1实际上就是实例方法中的self
-
类方法的调用
#使用类名或类的对象名直接调用 Student.cm() # 我是类方法 stu1.cm() # 我是类方法
-
静态方法的调用
方式同 类方法
5.动态绑定属性和方法
***续接 2.2中的代码***
stu1=Student('张三',20)
stu2=Student('李四',30)
#为stu2动态绑定一个属性
stu2.gender='女'
#为stu1动态绑定一个方法
def show():
print('定义在类之外,称为函数')
stu1.show=show #注意不带括号
stu1.show() #定义在类之外,称为函数
三、面向对象的特征
1.封装
-
作用:提高程序的安全性,减少程序的复杂度
-
方法:在属性前面加两个下划线
-
实现:
class Student: native_pace='吉林' def __init__(self,name,age): self.name=name self.__age=age #变量前加两个下划线,表示不希望此属性在类之外使用 def show(): print(self.name,self.__age) # self.__age可以在类的内部使用 stu1=Student('Jack',23) print(stu1.name) #返回Jack print(stu1.__age) #报错 print(stu1._Student__age)#返回20 ;使用 " 对象名._类名__age "仍可在外部访问,但不建议这么做。
2.继承
<1>特点
- Python支持多继承,即一个子类可以继承多个父类
- 如果一个类没有继承任何一个类,则默认继承Object
- 定义子类时必须在其构造函数中调用父类的继承函数
<2>创建子类父类
class 子类类名(父类01,父类02,...):
pass
class Person:
def __init__(self,name,age):
self.name=name
self.age=age
#创建子类: class 子类名(父类名)
class Student(Person):
def __init__(self,name,age,stu_num):
super().__init__(name,age) #通过super()函数来调用父类的init方法
self.stu_num=stu_num
<3>方法重写
class Person:
def __init__(self,name,age):
self.name=name
self.age=age
def info():
print(self.name,self.age)
class Student(Person):
def __init__(self,name,age,stu_num):
super().__init__(name,age)
self.stu_num=stu_num
def info(): # 父类的info()只输出name和age,需要通过方法重写才能输出学号stu_num
super().info() #调用父类的方法
print(self.stu_num)
<4>object类
-
obiect类是所有类的父类,因此所有类都有object类的属性和方法
-
内置函数—— dir()可以查看指定对象所有属性
-
object有一个 _ _ str() _ _ 方法,用于返回对于“对象的描述”。
对应于内置函数str()经常用于print()方法,帮我们查看对象的信息,所以我们经常会对 _ _ str() _ _进行重写
class Student:
pass
stu=Student()
print (dir(stu)) #返回对stu的所有属性,正确方式为object.dir(stu),但object可以省略
print(stu) #返回 stu的内存地址
****重写 __str()__方法****
class Student:
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self):
return '我的名字是{0},今年{1}岁'.format(self.name,self.age)
stu=Student('张三',20)
print(stu) #返回:我的名字是张三,今年20岁;不再返回内存地址
3.多态
四、特殊属性和特殊方法
作用 | ||
---|---|---|
_ _dict _ _ | 特殊属性 | 获得类对象或实例对象所绑定的所有属性和方法的字典 |
_ _ len _ _ () | 特殊方法 | 通过重写,让内置函数len()的对象可以是任自定义类型 |
_ _ add_ _() | 特殊方法 | 通过重写,让自定义对象具有"+"的功能 |
_ _new _ _() | 特殊方法 | 用于创建对象 |
_ _ init_ _() | 特殊方法 | 对创建的对象进行初始化 |
***重写__add__()方法***
class Student:
def __init__(self,name):
self.name=name
def __add__(self,other):
return self.name+other.name
stu1=Student('张三')
stu2=Student('李四')
s=stu1+stu2 # 实现了两个对象的加法运算
print(S) #返回 :张三李四
s=stu1.__add___(stu2)
print(S) #返回 :张三李四
***重写__len__()方法***
lst=[1,2,3,4]
print(len(lst)) #返回:4 ;len是内置函数
print(lst.__len__()) #返回:4
class Student:
def __init__(self,name):
self.name=name
def __len__(self):
return len(self.name)
stu1=Student('Jack')
print(len(stu1)) #返回:4
五、Python 程序的组织和管理
1.源程序和模块结构
以主程序运行
***将此Python文件命名为calc01***
def add(a,b):
return a+b
print(add(10,20))
import calc01
print(calc01.add(100,300))
'''
返回:
30
3000 '''
***修改calc01.py文件***
def add(a,b):
return a+b
if __name__ == '__main__':
print(add(10,20)) #只有当点击calc01运行时,才会执行此语句
#此时再调用calc01.py文件中的函数不会再输出30.
2.模块的导入
<1>import方式:导入模块的所有内容
import <模块名>
#一行导入多个模块
import <模块1> [,<模块2> [,<模块3>]]
#简化模块的名称
import <模块名> as <别名>
使用方法:<模块名>.<函数名/属性>
import math #关于数学运算
print(dir(math)) #看看math这个模块有哪些可以用的方法或属性
print(math.pi)
<2>from方式:导入模块的指定内容
使用此方法可能会导致新进来的的名称覆盖掉当前命名空间已有的相同函数的名称,所以慎用此方法
from <模块名> import <函数名/属性名>
3.包
-
定义:包是一个分层次的目录结构,它将一组功能相近的模块组织在同一目录下
-
作用:代码规范,避免模块名称冲突
-
包与目录的区别:
“包” 含有 __ init __.py文件,目录中通常不含有此文件
包的导入名称一般比较长,可以进行简写
import package1.module_A
import package1.module_B as B
print(B.add())
math这个模块有哪些可以用的方法或属性
print(math.pi)
#### <2>from方式:导入模块的指定内容
使用此方法可能会导致新进来的的名称覆盖掉当前命名空间已有的相同函数的名称,所以==慎用==此方法
```python
from <模块名> import <函数名/属性名>
3.包
-
定义:包是一个分层次的目录结构,它将一组功能相近的模块组织在同一目录下
-
作用:代码规范,避免模块名称冲突
-
包与目录的区别:
“包” 含有 __ init __.py文件,目录中通常不含有此文件
包的导入名称一般比较长,可以进行简写
import package1.module_A
import package1.module_B as B
print(B.add())