python3之模块和面向对象

2019-05-16  本文已影响0人  rr1990

一、模块介绍

一个.py文件就是一个模块,模块中可以定义函数、类和变量。

1. 引用模块

import 模块1[, 模块2..., 模块n]
import 模块名.函数名
import 模块名.变量名
from 模块名 import 方法1[, 方法2, ...方法n]
从模块中导入指定的方法到当前命名空间
from 模块名 import *
把模块中的所有内容全部导入到当前命名空间
from 模块名 import 方法1 as name
从模块中导入方法1并指定别名为name,调用时name.XXX或name(XXX)

2. 模块中特殊属性

2.1. __name__属性

模块就是一个可执行的.py文件,一个模块被另一个程序引入。
如果不想让模块中的某些代码执行,可以用__name__属性。每个模块都有一个__name__属性。
当前文件如果为程序的入口文件时,则__name__ == "__main__"。当__name__属性的值为"__main__"时,则表明该模块自身在执行;否则被引用其他文件。

3. 包

防止模块命名冲突,引入按目录来组织模块的方法,称为包package。
引入包后,只要顶层的包与其他文件不冲突,此包下的模块就不会与其他文件发生冲突。
每个包下必须存在一个__init__.py文件,此文件内容可为空。
__init__.py文件的作用:避免一些滥竽充数的名字,且目录下只有存在此文件才可认为此目录为一个包。

4. 安装第三方模块

(1)前提:安装python时安装有pip
查看是否安装有pip方法,命令行输入pip -V

C:\Users\admin>pip -V
pip 18.1 from d:\programs\python\python36\lib\site-packages\pip (python 3.6)

(2)安装三方模块

(1)安装Pillow模块:
C:\Users\admin>pip install Pillow
Requirement already satisfied: Pillow in d:\programs\python\python36\lib\site-packages (5.3.0)
You are using pip version 18.1, however version 19.1.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.
---报错,提示升级pip
(2)升级pip
遇到过升级pip后无法找到pip模块:
File "D:\Programs\Python\Python36\Scripts\pip.exe\__main__.py", line 5, in <module>
ModuleNotFoundError: No module named 'pip'。但实际上有pip文件。
解决方案:
首先执行:python -m ensurepip
再升级pip:python -m pip install --upgrade pip

(3)查看pip安装的模块

二、面向对象

1. 面向过程和面向对象的介绍

1.1. 面向过程:

1.2. 函数式:

1.3. 面向对象:

2. 类

2.1. 类的介绍

2.2. 创建类

-----创建类的格式:
class 类名(父类1, 父类2...): 
   属性
   行为

-----访问类
1. 使用类实例化对象
实例化对象格式:对象名 = 类名(参数列表)
注:类没有参数,类名后的小括号也不可省略。
2. 访问属性
访问属性格式:对象名.属性名
赋新值:对象名.属性名 = 新值
3. 访问方法
访问方法格式:对象名.方法名(参数列表)
# 创建不含继承的类
class Student1:
    name = "zhangsan"       # 属性

    def getScore(self, score):      # 方法
        print("这个学生的分数是:", score)

# 获取类的实例化对象
student1 = Student1()
# 访问属性
getName = student1.name
print(getName)              # zhangsan
# 访问方法
student1.getScore(90)       # 这个学生的分数是: 90
# 创建含继承的类
class Student2(object):
    name = "zhangsan"       # 属性

    def getScore(self, score):      # 方法
        print("这个学生的分数是:", score)

# 获取类的实例化对象
student2 = Student2()
# 访问属性
getName = student2.name
print(getName)              # zhangsan
# 访问方法
student2.getScore(80)       # 这个学生的分数是: 80

2.3. 构造函数

-----创建类的格式:
class 类名(父类1, 父类2...): 
    def __init__(self, 属性1, 属性2,...):      # 属性
        self.属性1 = 属性1      
        self.属性2 = 属性2
        ...
   def 方法函数(self, 方法参数1, 方法参数2, ...)
        行为

-----访问类
1. 使用类实例化对象
实例化对象格式:对象名 = 类名(属性参数列表)
注:类没有参数,类名后的小括号也不可省略。
2. 访问属性
访问属性格式:对象名.属性名
赋新值:对象名.属性名 = 新值
3. 访问方法
访问方法格式:对象名.方法名(方法参数列表)
# 创建含构造函数的类
class Student3(object):
    def __init__(self, name):
        self.name = name

    def getScore(self, score):
        print("这个学生的分数是:", score)

# 获取类的实例化对象
student3 = Student3("liNing")
# 访问属性
print(student3.name)        # liNing
# 访问方法
student3.getScore("70")     # 这个学生的分数是: 70

2.4. self介绍

1. -----类的内部访问属性和方法-----
访问属性格式:self.属性名
访问方法格式:self.方法名(参数)
获取类名:self.__class__
2. -----类的外部访问属性和方法-----
访问属性格式:类的实例化对象.属性名
访问方法格式:类的实例化对象.方法(参数)
"""类的内部和外部分别获取属性和方法"""
class Student4(object):
    def __init__(self, name):
        self.name = name

    def getScore(self, score):
        return score

    def getStudentInfo(self, score):
        print("姓名:%s,分数:%d" % (self.name, self.getScore(score)))       # 类的内部访问属性和方法

    def getClassName(self):             # 获取类名
        print(self.__class__)

    def createObject(self):             # 创建对象
        newObject = self.__class__("LiHong")
        print(newObject)

# 获取类的实例化对象
student4 = Student4("LiMing")
# 类的外部访问属性
print(student4.name)                # LiMing
# 类的外部访问方法
student4.getStudentInfo(80)         # 姓名:LiMing,分数:80
student4.getClassName()             # <class '__main__.Student4'>
student4.createObject()             # <__main__.Student4 object at 0x000000000234E240>

2.5. 析构函数

class Student5(object):
    def __init__(self, name):
        self.name = name

    def getScore(self, score):
        return score

    def getStudentInfo(self, score):
        print("%s的分数是%d" % (self.name, self.getScore(score)))

    def __del__(self):
        print("这是个析构函数")

student5 = Student5("LiMing")
print(student5.getScore(80))
student5.getStudentInfo(80)
# del student5                  # 删除student5对象
# student5.getStudentInfo()     # 删除student5对象后,不可再使用此对象,否则会提示对象未被定义
print("代码结束")
"""运行结果:
80
LiMing的分数是80
代码结束
这是个析构函数
"""

2.6. 类中特殊方法__str__()__repr__()

class Student6(object):
    def __init__(self, name, sex, score):
        self.name = name
        self.sex = sex
        self.score = score

    def getStudentInfo(self):
        print("%s的分数是%d" % (self.name, self.score))

    def __str__(self):      # 这是个__str__函数
        return "name=%s, sex=%s, score=%d" % (self.name, self.sex, self.score)

    def __repr__(self):     # 这是个__repr__函数
        return "name=%s, sex=%s, score=%d" % (self.name, self.sex, self.score)

# 获取类的实例化对象
student6 = Student6("LiMing", "female", 80)
# 打印对象
print(student6)         # name=LiMing, sex=female, score=80

2.7. 类中私有属性

"""外部无法访问私有属性"""
class Person1(object):

    def __init__(self, name, sex, money):
        self.name = name
        self.sex = sex
        self.__money = money

    def getInfo(self):
        print("%s拥有%d钱" % (self.name, self.__money))        # 内部可以使用私有属性__money

person1 = Person1("LiMing", "female", 1000)
# print(person1.__money)       # 报错,外部无法访问私有属性__money
# person1.__money = 100       # 外部也可以访问此私有属性,但此私有属性名已发生改变,故不允许此用法
"""外部修改和获取私有属性的方法"""
class Person2(object):
    def __init__(self, name, sex, money):
        self.name = name
        self.sex = sex
        self.__money = money

    def setMoney(self, money):      # 修改私有属性的值
        if money < 0:
            money = 0
        self.__money = money

    def getMoney(self):             # 获取私有属性的值
        return self.__money

person2 = Person2("LiMing", "female", 1000)
print(person2.getMoney())           # 1000
person2.setMoney(200)              
print(person2.getMoney())           # 200

3. 面向对象的简单例子

"""用例:人开车
分析:需要创建三个类,人、车、油箱
人---类名:Person;属性:car;方法:开车、加油
车---类名:Car;属性:油箱;方法:车跑
油箱---类名:OilBox;属性:油
"""
class OilBox(object):      
    """创建一个油箱"""
    def __init__(self, oil):
        self.oil = oil
class Car(object):
    """创建一个车"""
    def __init__(self, oilBox):
        self.oilBox = oilBox      # 油箱

    def run(self):
        """车执行跑操作"""
        if self.oilBox.oil == 0:
            print("没有油了")
        else:
            self.oilBox.oil -= 10
            print("剩余油量", self.oilBox.oil)
class Person(object):
    """创建一个人"""
    def __init__(self, car):
        self.car = car

    def driver(self):
        """人要开车, 车要跑"""
        self.car.run()

    def addOil(self, oil):
        """给车加油"""
        self.car.oilBox.oil = oil
"""使用面向对象实现人开车操作"""
from Examples.Example1.person import Person
from Examples.Example1.car import Car
from Examples.Example1.oilBox import OilBox

oilBox = OilBox(100)    # 创建一个油箱对象
car = Car(oilBox)        # 创建一个车对象
person = Person(car)    # 创建一个人对象
person.driver()          # 人开车
person.addOil(200)    # 人加油
person.driver()

三、继承

1. 继承定义

2. 单继承

单继承即仅继承一个类。

2.1. 子类属性的继承和重写

子类中构造函数调用父类构造函数有两种方法:
第一种:父类.__init__(self, 参数1, 参数2, ...)
第二种:super(子类, self).__init__(参数1, 参数2, ...)

2.2. 子类方法的继承和重写

2.3. 子类继承单个父类的例子

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eat(self, food):
        print("%s正在吃%s" % (self.name, food))
"""------子类使用父类的属性和方法------"""
class Teacher1(Person):
    pass

# 子类使用父类的属性
teacher1 = Teacher1("A", 20)
print(teacher1.name, teacher1.age)  # A 20
# 子类使用父类的方法
teacher1.eat("rice")                # A正在吃rice

"""------子类重写父类的属性、直接使用父类的方法------"""
class Teacher2(Person):
    def __init__(self, name, age):
        """子类重写父类属性"""
        # Person.__init__(self, name, age)              # 重写构造函数的第一种方法
        super(Teacher2, self).__init__(name, age)       # 重写构造函数的第二种方法

# 子类使用父类的属性
teacher2 = Teacher2("A", 20)
print(teacher2.name, teacher2.age)  # A 20
# 子类直接使用父类的方法
teacher2.eat("fish")                # A正在吃fish

"""------子类重写父类属性且添加新的属性,子类重写父类方法------"""
class Teacher3(Person):
    def __init__(self, name, age, sex):
        """子类重写父类属性"""
        # Person.__init__(self, name, age)              # 重写构造函数的第一种方法
        super(Teacher3, self).__init__(name, age)       # 重写构造函数的第二种方法
        self.sex = sex

    def eat(self, food):
        """子类重写父类方法"""
        print("%s is eating %s" % (self.name, food))

teacher3 = Teacher3("A", 20, "female")
print(teacher3.name, teacher3.age, teacher3.sex)  # A 20 female
# 子类直接使用父类的方法
teacher3.eat("fish")            # A is eating fish

3. 多继承

多继承即同时继承多个类。

3.1. 子类属性的继承和重写

父类1.__init__(self, 参数1, 参数2, ...)
父类2.__init__(self, 参数1, 参数2, ...)
...
父类n.__init__(self, 参数1, 参数2, ...)

3.2. 子类方法的继承和重写

3.3. 子类继承多个父类的例子

class Programmer(object):       # 程序员
    def __init__(self, language):
        self.language = language

    def writeCode(self):
        print("用%s语言写代码" % self.language)

    def phone(self):
        print("程序员在打电话")

class Chef(object):         # 厨师
    def __init__(self, food):
        self.food = food

    def cooking(self):
        print("烹饪%s" % self.food)

    def phone(self):
        print("厨师在打电话")
"""------子类继承多个父类,子类重写父类的属性------"""
class Person1(Programmer, Chef):

    def __init__(self, name, age, language, food):
        """子类重写父类属性"""
        Programmer.__init__(self, language)
        Chef.__init__(self, food)
        self.name = name
        self.age = age

# 创建类的实例化对象
person1 = Person1("A", 18, "Python", "fish")
# 对象的属性
print(person1.name, person1.age, person1.language, person1.food)    # A 18 Python fish
# 子类使用父类方法
person1.writeCode()         # 用Python语言写代码
person1.cooking()           # 烹饪fish
# 父类存在相同的方法,子类使用时默认使用括号中排名在前的方法
person1.phone()             # 程序员在打电话

"""------子类继承多个父类,子类重写父类的属性且重写父类方法------"""
class Person2(Programmer, Chef):

    def __init__(self, name, age, language, food):
        """子类重写父类属性"""
        Programmer.__init__(self, language)
        Chef.__init__(self, food)
        self.name = name
        self.age = age

    def phone(self):
        print("%s在打电话" % self.name)

person2 = Person2("A", 20, "Python", "fish")
person2.phone()         # A在打电话

四、多态

多态:一种事件的多种形态。意味着即使不知道变量指向什么对象,也能够对此对象执行操作,且操作的行为跟随对象所必的类型而变。

class Animal(object):
    def __init__(self, name):
        self.name = name

    def run(self):
        print("%s在跑步" % self.name)

"""采用多态方式实现"""
class Person(object):
    def leadAnimalRun(self, animal):    # animal采用的多态方式
        print("人训练动物跑步")
        animal.run()

person = Person()
cat = Animal("Cat")
person.leadAnimalRun(cat)
dog = Animal("Dog")
person.leadAnimalRun(dog)

五、对象属性和类属性

一个类所包含的属性有:对象属性和类属性。

1. 类属性

1.1. 访问类属性

1.2. 修改类属性

2. 对象属性

class Person1(object):
    count = 0                   # 类属性

    def __init__(self, name):   # 对象属性
        self.name = name

    def testClassAttribute(self):
        """通过类修改类属性值"""
        Person1.count = 50  # 通过类名的方式给类属性值赋新值,相当于全局变量
        print(Person1.count)  # 50
        print(self.count)  # 50
        """通过对象修改类属性值"""
        self.count = 60  # 通过对象的方式给类属性值赋新值,相当于局部变量,仅对当前对象生效
        print(Person1.count)  # 50
        print(self.count)  # 60

    def testObjectAttribute(self):
        """对象属性"""
        self.name = 'B'
        print(self.name)    # B

person1 = Person1("A")
person1.testClassAttribute()
print(Person1.count)        # 50
print(person1.count)        # 60

person1.testObjectAttribute()
person1.name = "C"          # 类外部修改对象属性值
person1.age = 20            # 类外部新建新的属性,并赋值
print(person1.name, person1.age)         # C 20

六、动态给实例添加属性和方法

1. 动态给实例添加属性和方法

class Person(object):
    pass

person = Person()
"""给对象动态添加属性"""
person.name = "LiMing"
print(person.name)      # LiMing
"""给对象动态添加方法"""
from types import MethodType    
def getAge(self, age):
    print("%s的年龄:%d" % (self.name, age))
person.ageMethod = MethodType(getAge, person)
person.ageMethod(20)            # LiMing的年龄:20

2. 限制对象中添加的动态属性

定义类时定义一个特殊的属性__slots__,此属性可限制动态添加的属性。

from types import MethodType    
class Student:
    __slots__ = ("name", "age", "sex", "scoreInfo")      # 表示给Student类添加属性时仅可添加name、age、sex、scoreInfo

student = Student()
student.name = "LiHong"
print(student.name)             # LiHong
# student.work = "Doctor"       # 会报错提示此对象无work属性
# print(student.work)
def getScore(self, score):
    print("%s的分数:%d" % (self.name, score))
student.scoreInfo = MethodType(getScore, student)
student.scoreInfo(90)           # LiHong的分数:90

七、运算符重载

对两个对象执行运算操作,则提示类型不支持(TypeError: unsupported operand type(s)),因此需要借助运算符重载。

1. 常用的运算符重载

构造函数__init__
解析函数__del__
打印函数__repr__、__str__
函数调用__call__
函数属性__getattr__、__setattr__、__delattr__
数字运算符函数:__add__(self, other)、__sub__(self, other)、__mul__(self, other)、__div__(self, other)
...
class Student:
    def __init__(self, score):
        self.score = score

    def __add__(self, other):
        return Student(self.score + other.score)

    def __str__(self):
        return "score=%d" % self.score

student1 = Student(70)
student2 = Student(80)
print(student1 + student2)                  # score=150
print(student1.__add__(student2).score)     # 150

2. __call__介绍:

__call__是一个可调用对象,而函数和类都属于可调用对象。
通过__call__方法可以将一个类实例化对象变成一个可调用对象。使用__call__还可以

class Person:
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

    def __call__(self, name, sex):
        self.name = name
        self.sex = sex

person = Person("LiMing", 20, "female")     # 实例化对象
person("LiHong", "male")                    # 将实例变为可调用的对象
print(person.name, person.sex, person.age)      # LiHong male 20
上一篇下一篇

猜你喜欢

热点阅读