对象
对象:
对象是内存中专门用来存储数据的一块区域。
对象由三部分组成:
- 对象的标识(id )
- 对象的类型(type)
- 对象的值(value)
类(class)
类是一个用来创建对象的对象。
类是一个type类型的对象,定义类实际上就是定义了一个type类型的对象。
定义类:
在类的代码块中,可以定义变量和函数。类中定义的函数我们称为方法,这些方法可以通过该类的所有实例来访问
- 调用方法:对象.方法名()
方法调用和函数调用的区别:
- 函数调用时传几个实参就会有几个实参
- 方法调用默认传递一个参数,所以方法中至少要定义一个形参
注意:方法调用时,第一个参数由解析器自动传递,所以定义方法时,至少定义一个形参。
一般情况下,属性保存到实例对象中,而方法需要保存到类对象中
方法每次被调用时,解析器都会自动传递一个实参,第一个参数就是调用方法的对象本身。一般我们都会将这个参数命名为 self
# 语法
class 类名([父类]):
代码块
# 定义一个最简单的类
class Myclass():
pass
使用类创建对象:
class MyClass():
pass
myclass = MyClass()
myclass1 = MyClass()
myclass2 = MyClass()
# myclass,myclass1,myclass2都是MyClass的实例,都是一类对象
print(myclass,type(myclass))
print(myclass1,type(myclass1))
print(myclass2,type(myclass2))
# isinstance()用来检查一个对象是否是一个类的实例
result = isinstance(myclass,MyClass)
print(result)
对象的初始化
- 在类中可以定义一些特殊方法,以__开头,以__结尾。
- 特殊方法会在特殊时刻自动调用,我们不要尝试去调用
创建一个Person类
class Person() :
def __init__(self,name,age,gender) :
self.name = name
self.age = age
self.gender = gender
def say_hello() :
print('我的名字叫%s'%self.name)
# 创建Person类的实例
person = Person('小明',18,'男')
print(person)
print(person.name,person.age,person.gender)
创建对象的流程:
- 创建一个变量
- 在内存中创建一个新对象
- init(self) 方法执行
- 将对象的 id 赋值给变量
- init 可以用来向新创建的对象中初始化属性。调用类创建对象时,类后边的所有参数都会依次传递到init() 中
面向对象三大特征
封装
- 确保对象中的数据安全
继承
- 保证了对象的可扩展性
多态
- 保证了程序的灵活性
封装
封装指的是隐藏对象中一些不希望被外部所访问到的属性或方法。
封装是面向对象的三大特性之一。
使用封装增加了类的定义的复杂程度,但是确保了数据的安全。
隐藏对象中的属性(一)
- 隐藏对象中的属性可以将属性名改为一个外部不知道的名字
- 通过getter和setter方法来调用和修改属性的值
class Person() :
def __init__(self,name) :
self.hidden_name = name
def set_name(self,name) :
self.hidden_name = name
def get_name(self) :
return self.hidden_name
person = Person('小明')
print(person.get_name())
person.set_name('李明')
print(person.get_name())
隐藏对象的属性(二)
- 隐藏属性可以使对象的属性名使用双下划线 __ 开头,例如 __xxx
- 双下划线开头的属性使对象的隐藏属性,隐藏属性只能在类的内部访问。
- 隐藏属性的原理是python自动将属性名修改为 _类名__属性名 这种形式
使用__开头的属性实际上依然可以在外部访问,所以这种方式一般不使用。
class Person() :
def __init__(self,name) :
self.__name = name
def set_name(self,name) :
self.__name = name
def get_name(self) :
return self.__name
person = Person('小明')
print(person._Person__name)
person._Person__name = '李明'
print(person.get_name())
#小明
#李明
隐藏对象的属性(三)(推荐使用)
一般我们会将私有属性(不希望被外部访问的属性)以 _ 开头。
- property装饰器用来将一个get方法转换为对象的属性。添加property装饰器以后,我们可以像调用属性一样使用get方法。
- 使用property装饰的方法,方法名必须和属性名相同
- 属性名.setter 装饰器同理,用于setter方法
class Person():
def __init__(self,name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self,name):
self._name = name
person = Person('小明')
print(person.name)
person.name = '李明'
print(person.name)
# 小明
# 李明
继承
- 继承是面向对象的三大特征之一。
- 通过继承我们可以使一个类获取到其他类中的属性和方法。
- 在定义类时可以在类名后的括号中指定当前类的父类(超类、基类、super),子类(衍生类)可以直接继承父类中所有的属性和方法。
创建类时如果省略了父类,则默认父类为object。object时所有类的父类,所有类都继承自object。
class Person:
def sleep(self):
print('睡觉')
def eat(self):
print('吃饭')
class Man(Person):
def work(self):
print('赚钱养家')
man = Man()
man.sleep()
man.eat()
man.work()
issubclass()
issubclass() :检查一个类是否是另一个类的子类
isinstance()
isinstance() :检查一个对象是否是一个类的实例
class Person:
def sleep(self):
print('睡觉')
def eat(self):
print('吃饭')
class Man(Person):
def work(self):
print('赚钱养家')
man = Man()
# 检查Man() 是否是Person()的子类
print(issubclass(Man,Person))
# 检查man是否是Man()的实例
print(isinstance(man,Man))
supper()
- 父类中的所有的方法都会被子类继承,包括特殊方法,所以也就可以重写特殊方法。
- 我们希望可以直接调用父类的 init 来初始化父类中定义的属性
supper() 可以用来获取当前类的父类,并且通过 super() 返回对象调用方法时,不需要传递self
class Person:
def __init__(self,name):
self._name = name
def sleep(self):
print('睡觉')
def eat(self):
print('吃饭')
@property
def name(self):
return self._name
@name.setter
def name(self,name):
self._name = name
# 父类中的所有方法都会被子类继承,包括特殊方法,当然也可以重写特殊方法
class Man(Person):
def __init__(self,name,age):
#super()可以用来获取当前类的父类
#通过supper()返回对象调用父类方法时,不需要传递self
super().__init__(name)
self._age = age
def work(self):
print('赚钱养家')
@property
def age(self):
return self._age
@age.setter
def age(self,age):
self._age = age
man = Man('张三',22)
print(man.name) # 张三
print(man.age) #22
多重继承
- 在Python中支持多重继承,即一个类可以同时继承多个父类
- 在类名后面的()中添加多个类来实现多重继承
- 多重继承会使子类同时拥有多个父类,并且会获取到所有父类中的方法
- 在开发中没有特殊的情况,应该尽量避免使用多重继承,因为多重继承会让我们的代码过于复杂
- 如果多个父类中有同名的方法,则会现在第一个父类中寻找,然后找第二个,然后找第三个…以此类推
- 前边父类的方法会覆盖后边父类的方法。
class A(object):
def test(self):
print('aaa')
class B(object):
def test(self):
print('bbb')
class C(A,B):
pass
c = C()
c.test() # aaa
重写(覆盖)
重写:如果在子类中有和父类同名的方法,则通过子类实例去调用方法时,会调用子类的方法而不是父类的方法
- 当我们调用一个对象的方法时会优先去当前对象的类中寻找,如果有则调用;
- 如果没有找到,就会去当前类的父类中寻找,如果有则调用;
- 如果父类中没有找到,则去父类的父类中寻找,直到找到object类也没有找到就会报错。
多态
多态:一个对象可以以不同的形态去呈现
多态是面向对象的三大特征之一。
类中的属性和方法
类属性
- 直接在类中定义的属性是类属性。
- 类属性可以通过类或类的实例访问到
- 类属性只能通过类对象来修改,无法通过实例对象修改
实例属性
- 通过实例对象添加的属性属于实例属性
- 实例属性只能通过实例对象来访问和修改,类对象无法访问修改
类方法
- 在类内部使用 @classmethod 来修饰的方法属于类方法
- 类方法的第一个参数是cls,也会被自动传递,cls就是当前的类对象
- 类方法和实例方法的区别:实例方法的第一个参数是self,而类方法的第一个参数是cls
- 类方法可以通过类调用,也可以通过实例调用,没有区别
实例方法
- 在类中定义,以self为第一个参数的方法都是实例方法
- 实例方法在调用时,python会将调用对象作为self传入
- 实例对象可以通过实例和类去调用
- 当通过实例调用时,会自动将当前调用对象作为self传入
- 当通过类调用时,不会自动传递self,此时我们必须手动传递self
静态方法
- 在类中使用 @staticmethod 来修饰的方法属于静态方法
- 静态方法不需要指定任何默认参数,静态方法可以通过类和实例调用
- 静态方法一般都是一些工具方法,和当前类无关,相当于一个保存到当前类中的函数
class A(object):
#类属性,直接在类中定义
num = 0
def __init__(self):
#实例属性,通过实例对象添加的属性
self._name = '悟空'
#实例方法,在类中定义,以self为第一个参数
def test(self):
print('test方法,也是一个实例方法')
#类方法,在类内部使用@classmethod修饰
@classmethod
def test1(cls):
print('test1方法,也是一个类方法',cls)
print(cls.num)
#静态方法
@staticmethod
def test2():
print('test2方法,也是一个静态方法')
a = A()
#实例属性,通过实例对象添加的属性
a.res = 2
print(a.res)
模块
- 模块化是指将一个完整的程序分解为一个个小的模块,通过模块组合来搭建出一个完整的程序
- 模块化方便开发,方便维护,代码可以复用
- python中一个py文件就是一个模块(命名要符合标识符的规范)
在一个模块中引入外部模块
- 可以引入同一个模块多次,但是模块的实例只会创建一个
- import 可以在程序的任意位置调用,一般都写在第一行
# 引入模块的语法
import 模块名
import 模块名 as 模块别名
模块内部有一个__name__属性,通过这个属性可以获取到当前模块的名字。主模块是直接通过python执行的模块,__name__属性值为__main__的模块是主模块,一个程序只有一个主模块。
也可以只引入模块中的部分内容
# 语法
from 模块名 import 变量1,变量2,...
# 引入模块所有内容
from 模块名 import *
# 也可以为引入的变量使用别名
from 变量名 import 变量 as 别名
包(package)
- 包也是一个模块。普通的包是一个py文件,包是一个文件夹。
- 包中必须要有一个__init__文件,这个文件可以包含包中的主要内容。
- __pycache__是模块的缓存文件。
- py代码在执行前,需要被解析器先转换为机器码,然后再执行
- 所以在使用模块(包)时,也需要将模块的代码先转换为机器码然后再交由计算机执行
- 为了提高程序运行的性能,python会在编译过一次以后,将代码保存到一个缓存文件中。这样在下次加载这个模块(包)时,就可以不再重新编译而是直接加载缓存中编译报的代码即可
Python的标准库
sys模块里面提供了一些变量和函数,使我们可以获取到Python解析器的信息,或者通过函数来操作Python解析器
- sys.argv :获取执行代码时,命令行中所包含的参数
- sys.modules :获取当前程序中引入的所有模块。modules是一个字典,字典的key是模块的名字,字典的value是模块对象。
- sys.path :一个列表,列表中保存模块的搜索路径
- sys.platform :表示当前Python运行的平台
- sys.exit() :函数用来退出程序
pprint模块提供了一个 pprint() 方法,该方法可以用来对打印的数据做简单的格式化
os 模块让我们可以对操作系统进行访问
- os.environ :通过这个属性可以获取到系统的环境变量
- os.system() :可以用来执行操作系统的命令