linRichielinRichie
前端
Python
Linux
ChatGPT
  • B 站
  • 500px
前端
Python
Linux
ChatGPT
  • B 站
  • 500px
    • Python学习指南
  • 快速开始

    • Python: 输入与输出 (I/O)
    • Python: 异常处理 try-except
    • Python: List深入概述
    • Python: 面向对象编程(OOP)
  • Python 语法库函数

    • 语法库目录
    • 库

      • library目录
      • argparse:解析命令行参数
      • difflib:比较序列并生成差异信息
      • dnspython: DNS处理库
      • IPy:IP地址处理库
      • logging:记录和管理日志信息
      • os:访问和操作操作系统
      • psutil:系统性能信息库
      • re:正则表达式库
      • smtplib:邮件发送库
    • 函数

      • function目录
      • any() 函数
      • input 函数
      • lambda 和 map 函数
      • reversed()函数
      • zip()函数
    • 语句

      • statement目录
      • import 语句
      • Try/Exception 异常
    • 概念

      • concept目录
      • 深拷贝与浅拷贝
      • 列表、字典与元组
      • 文件读写
      • IO: 输入与输出
      • 逻辑判断与条件语句
      • OOP 面向对象:class
      • OOP: 面向对象编程
  • SQLAlchemy

    • 获取insert或者update的id
  • Pandas

    • Pandas目录
    • Pandas:基础操作
    • Pandas:数据处理与转换
    • Pandas: 数据写入 excel 表格
  • Python前端框架

    • Flask

      • 1. Flask简介
      • 2. Flask程序基本结构
      • 3. Flask请求-响应循环
      • 4. flask案例: 框架网页查询IP
      • Python: Flask中的GitHub OAuth
    • Django

      • chapter-01:Django框架认识

        • 1.1 Django的产生背景
        • 1.2 MTV设计模式
        • 1.3 Django 主要功能模块
      • chapter-02:开发环境配置

        • 2.1 Python的安装与配置
        • 2.2 虚拟环境安装与配置
        • 2.3 Django安装与配置
        • 2.4 MySQL安装配置
      • chapter-03:项目框架搭建

        • 3.1 Django管理工具-创建项目骨架
        • 3.2 修改项目的默认配置
        • 3.3 初始化项目环境
      • chapter-04:ORM应用与原理剖析

        • 4.1 构建POST应用需要的数据集
        • 4.2 Model相关的概念和使用方法
        • 4.3 Model的查询操作API
        • 4.4 ORM实现原理
      • chapter-05:Django管理后台

        • 5.1 将Model注册到管理后台
        • 5.2 管理后台实现原理
      • chapter-06:视图

        • 6.1 视图基础
        • 6.2 视图的高级特性和快捷方法
        • 6.3 基于类的通用视图
      • chapter-07:模板系统

        • 7.1 模板系统基础
        • 7.2 模板语言
      • chapter-08:表单系统

        • 8.2 使用表单系统实现表单: ModelForm
      • chapter-09:用户认证系统

        • 9.1 用户与身份认证
        • 9.2 权限管理
        • 9.3 用户认证系统应用
      • chapter-10:Django路由系统

        • 10.1 路由系统基础
      • chapter-11:Django中间件

        • 11.1 中间件基础
  • Python例子

    • Python: Linux的Shell命令
    • Python: PEP8自动格式化代码
    • Python: pip操作
    • Python: 业务服务监控
    • Python: 从文件逐行读取数据
    • 将链表转换为字符串
    • Python: 检查URL是否能正常访问
    • Python: 爬取网易云音乐
    • Python: 读取目录下的所有内容
    • 案例研究:文本统计
  • Python爬虫

    • 数据解析工具:Xpath
  • 算法题

    • 02:两数相加
    • 09:回文数
    • 13:罗马数值转换为整数
    • 14:最长公共前缀

OOP: 面向对象编程

  • 类的继承
  • 编写类
  • 方法
  • 定义的Person类的使用
  • 参数self
    • 提示
  • 显示对象
  • 灵活的初始化
  • 特性装饰器
  • 私有变量
  • 继承
    • 术语
    • 语法
  • 多态

  • OOP是组织程序的方法,提倡仔细设计和代码重用。

  • 大多数现代编程语言都支持OOP。

  • 本质上说,对象是一组数据以及操作这些数据的函数。

  • 前面学习的,一直在使用python对象,因为数字,字符串,列表,字典和函数都是对象。

  • 要创建新型对象,必须先创建类。

  • 本质上说,类就是设计蓝图,用于创建特定类型的对象。

  • 类指定了 对象 将 包含 那些 数据 和 函数,还指定 对象 和其他 类 之间的关系。对象 封装 了数据以及操作这些数据的 函数 。

  • 一个 重要 的OOP功能是 继承 :


类的继承

  • 创建新类时,可以让它 继承 既有类的 数据 和 函数 。这样可以避免重新编写代码。

编写类

  • 在OOP语言中, __init__ 被成为构造函数,因为它构造对象
  • 每次创建新对象时,都将调用构造函数。
  • 在Java和C++等语言中,创建对象时需要使用关键字 new
# 介绍OOP,编写一个表示人的类
# 代码
class Person:
    '''
    Class to represent a person
    '''
    
    def __init__(self):
        self.name = ''
        self.age = 0
        
        
# 上面的代码定义了一个名为Person类。
# 它定义了Person对象包含的数据和函数
# 上面的Person类很简单,包含数据name和age
# 当前唯一一个函数时__init__,这是用于初始化对象值的标准函数。
# 当你创建Person对象时,Python将自动调用__init__。

方法

  • 在类中定义的函数叫做:方法
  • 与__init__一样,方法的第一个参数必须时self(会详细地讨论self)

定义的Person类的使用

  • 要常见Person对象,只需调用Person()。

  • 这导致Python运行Person类中的函数__init__,并返回一个新的Person对象

  • 变量age和name包含在对象中,因此每个创建的Person对象都有自己的name和age

  • 要访问name和age,必须使句点表示法指定存储他们的对象

## 下面的方法可以使用定义Person类
p = Person()
print(p)
print(p.age)
print(p.name)
p.age = 35
print(p.age)
p.name = 'Nome'
print(p.name)


## 在这个例子中。变量p 指向一个 Person对象。
## 从 Person类的定义可知,Person对象包含变量 age 和 name 
## 可以像使用常规变量那样使用。
## 但必须使用句点表示法:即: p.age 和 p.name
## Python自动给每个对象添加特殊变量self
## 这个self变量指向本省,让类中的函数能够明确地引用对象地数据和函数

'''
    <__main__.Person object at 0x06B88130>
    0
    
    35
    Nome
'''

参数self

  • 在上面的例子中,调用Person()时,没有提供任何参数,但函数__init__(self)期望获得名为self的输入。
  • 这是因为在OOP中,self 是一个指向对象本身的变量。概念简单。理解不容易

提示

  • 所有类都应该有方法__init__(self),这个方法的职责是初始化对象,如初始化对象的变量。

  • 方法__init__仅被调用一次-------在对象被创建时。

  • 可根据需要给__init__指定其他参数

  • 遵循Python的标准做法,将__init__的第一个参数命名为self。

  • 并非必须这样做,可根据自己的喜好使用任何变量名(而不是self)。

  • 在python中,可像其他数据类型一样使用对象:可将他们传递给函数,存储到列表和字典中、保存到文件中等等

显示对象

  • 方法是类中定义地函数。
  • 下面给Person类添加一个方法,用于打印Person对象的内容
## 打印 Person对象的内容

class Person:
    '''
    Class to represent a person
    '''
    def __init__(self):
        self.name = ' '
        self.age = 0
    def display(self):
        print("Person('%s',%d)" % (self.name, self.age))
        
# 方法display 将Person 对象的内容以适合程序员阅读的格式打印到屏幕上

p = Person()
p.display()
p.name = 'Bob'
p.age = 35
p.display()

'''
    Person(' ',0)
    Person('Bob',35)
'''
## 方法display的效果很好,但还可以使用下面更好的方法
## python提供了一些特殊方法,让你能够定制对象以支持天衣无缝的打印
## 例如,特殊方法 __str__ 用于生成对象的字符串表示

class Persom():
    '''
    Class to represent a person
    '''
    def __init__(self):
        self.name = ' '
        self.age = 0
    def display(self):
        print("Person('%s',%d)" % (self.name,self.age))
    def __str__(self):
        return "Person('%s',%d) % (self.name,self.age)"

g = Person()
print(str(g))

## 还可以使用str简化display

class Persom():
    '''
    Class to represent a person
    '''
    def __init__(self):
        self.name = ' '
        self.age = 0
    def display(self):
        print(str(self))
    
    def __str__(self):
        return "Person('%s',%d) % (self.name,self.age)"
    
f = Person()
f.name = 'Mon'
f.age = 35
print(str(f))
print(display())


## 还可以定义特殊方法 __repr__ 返回对象的‘官方’(official)表示。
## 如:Person对象的默认官方表示不太实用
aaa = Person()
print(aaa)

## 通过添加方法 __repr__ 可控制这里打印的字符串。大大多数类中,方法 __repr__ 都与方法 __str__ 相同
class Persom():
    '''
    Class to represent a person
    '''
    def __init__(self):
        self.name = ' '
        self.age = 0
    def display(self):
        print(str(self))
    def __str__(self):
        return "Person('%s',age) % (self.name,self.age)"
    def __repr__(self):
        return str(self)
    
ccccc = Person()
print(ccccc)
print(str(ccccc))


## 创建自己的类和对象时,编写函数__str__ 和 __repr__ 几乎总是值得的。
## 对于显示对象的内容很有帮助,而显示对象的内容有助于调试程序

## 当定义了方法__repr__,但没有定义方法 __str__,则对象调用str()时,将执行__repr__
## 添加方法 __repr__ 后,可进一步简化发放display
##    def display(self):
##        print(self)
## 实际上,没有必要编写方法display

## python建议将对象的字符串表示设置为创建对象所需的代码。
## 这种约定,能够轻松地创建对象---只需要将字符串表示复制并粘贴到命令行

'''
    Person('',0)
    Person('',35)
    None
    Person('',0)
    Person('',0)
    Person('',0)
'''

灵活的初始化

  • 当需要创建特定的姓名和年龄的Person对象,可以用一个比较的方法是,在构造对象时将姓名和年龄传递给__init__
## 重写__init__
class Person:
    def __init__(self,name = '',age = 0):
        self.name = name
        self.age = age
    def __str__(self):
        return "Person('%s',age) % (self.name,self.age)"
    def __repr__(self):
        return str(self)
    
cde = Person('Moe',66)
cde
# Person('%s',age) % (self.name,self.age)

特性装饰器

  • 特性装饰器 融 变量的简洁与函数的灵活于一身。
  • 装饰器指出函数或方法有点特点,这是使用它们来指示设置函数和获取函数
  • 获取函数返回变量的值,将使用@property装饰器来指出
## 使用@property装饰器来指出
@property
def age(self):
    '''
    Return this person's age.
    '''
    return self._age

## 这个age方法除必不可少的self外,不接受任何参数。
## 我们在它前面加上了 @property,指出这是一个获取函数。这个方法的名称将被用于设置变量
## 还将底层变量self.age重命名为:self._age
## 在对象变量前加上下划线是一种常见的作法。
## 这里使用这个变量与方法age区分
## 修改Person类为下面的样子:

class Person:
    def __init__(self,name = '',age = 0):
        self._name = name
        self._age = age
    
    @property
    def age(self):
        return self._age
    
    @age.setter
    def age(self,age):
        if 0 < age <= 100:
            self._age = age
        
    def __str__(self):
        return "Person('%s',%s)" % (self._name,self._age)
    def __repr__(self):
        return str(self)

m = Person('Lia',33)
print(m)
m.age = 55
print(m.age)
m.age = -4
print(m.age)

n = Person('lin',25)
print(n)
n.age = 30
print(n)
n.age = -6
print(n)

## 给age提供了设置函数和获取函数,编写的代码就像直接使用变量age
## 差别在于:遇到代码m.age = -4/-6 时,python实际上将调用方法 age(self,age)
## 同样,遇到代码m.age时,将调用函数age(self,age)
## 这样的好处: 赋值语法简单,同时可控制变量的设置和获取方式

'''
    Person('Lia',33)
    55
    55
    Person('lin',25)
    Person('lin',30)
    Person('lin',30)
'''

私有变量

  • 不以下划线打头的变量是公有变量,任何代码都可以访问它们。
  • 为降低self._age被直接修改的可能性。主要有以下几种方式
    • 将其重命名为 self.__age,即在变量名开头包含两个下划线。
      • 两个下划线表明:age是私有变量,不应在Person类外直接访问它。

      • 要直接访问self.__age,需要在前面加上_Person

        p._Person__age = -44 print(p)

      • 这降低了直接修改的可能性

在编写大型程序时,一条使用的经验是:首先将所有对象变量都设置为私有的。当有充分理由的情况下将其改为公有的。

继承

  • 继承是一种重用类的集之,能够这样创建全新的类:给既有类的拷贝添加变量和方法
  • 当需要开发一款游戏,其中设计人类玩家和计算机玩家。为此,可以创建一个Player类,
  • 这个Player类。包含所有玩家都有的东西

术语

  • 在下面的例子中

  • 我们可以有下面的说法:

    • Human 扩展了 Player
    • Human 从 Player 派生而来
    • Human 是 Player 的字类。而 Player 是 Human 的超类
    • Human 是一个 Player
  • 最后一个术语,意味着所有人都是玩家。

  • 要创建类层次结构,一种方法是考虑类之间可能存在的是一个关系

语法

class New_name(Load_name)

- New_name: 表示的是:定义的新类的名称
- Load_name:表示的是:之前的或者存在的类的名称
# 案例 Player类
class Player:
    def __init__(self,name):
        self._name = name
        self._score = 0
        
    def reset_score(self):
        self._score = 0
        
    def incr_score(self):
        self._score = self._score + 1
    
    def get_name(self):
        return self._name
    
    def __str__(self):
        return "name = '%s',score = %s" % (self._name,self._score)
    
    def __repr__(self):
        return 'Player(%s)' % str(self)
    
abcdfg = Player('Moe')
print(abcdfg)

abcdfg.incr_score()
print(abcdfg)

abcdfg.reset_score()
print(abcdfg)


# name = 'Moe',score = 0
# name = 'Moe',score = 1
# name = 'Moe',score = 0
## 上面中,我们创建了一个类Player,下面,我们创建类Human继承Player类

## 创建一个Human类,表示人类玩家,一种办法是通过复制并粘贴新建Player类的一个拷贝,
## 在添加让玩家走棋的方法 make_move(self)。

## 另一种方法,就是使用继承,让Human类继承Player类的所有变量和方法。就不需要在进行编写

class Human(Player):
    pass


# 在Python中,pass语句表示“什么都不做”,对Human类来说,是一个完整而实用的定义。

hfg = Human('zhangsan')

print(hfg)

hfg.incr_score()
print(hfg)

hfg.reset_score()
print(hfg)


# name = 'zhangsan',score = 0
# name = 'zhangsan',score = 1
# name = 'zhangsan',score = 0

# 重写方法
# 上面的例子中。h 的字符串表示为 Player,但更准确的说法,h应该是Human。
# 修复这样的问题,可给Human定义 __repr__

class Human(Player):
    def __repe__(self):
        return 'Human(%s)' % str(self)
    
h = Human("zhangsan")
print(h)


# 创建 Computer 类
class Computer(Player):
    def __repr__(self):
        return 'Computer(%s)' % str(self)


    # name = 'zhangsan',score = 0

多态

  • 演示 OOP 的强大
  • 创建一个名为 Undercut的简单游戏。
  • 这个游戏中,两玩家同时选择一个1--10的整数
  • 如果一个玩家选择的整数比对方选择整数的小1,则该玩家获胜,否则平手
## Undercut游戏 案例

class Player:
    def __init__(self,name):
        self._name = name
        self._score = 0
        
    def reset_score(self):
        self._score = 0
        
    def incr_score(self):
        self._score = self._score + 1
    
    def get_name(self):
        return self._name
    
    def __str__(self):
        return "name = '%s',score = %s" % (self._name,self._score)
    
    def __repr__(self):
        return 'Player(%s)' % str(self)
    
    
def play_undercut(p1,p2):
    p1.reset_score()
    p2.reset_score()
    m1 = p1.get_move()
    m2 = p2.get_move()
    print("%s move: %s" % (p1.get_name(),m1))
    print("%s move: %s" % (p2.get_name(),m2))
    
    if m1 == m2 -1:
        p1.incr_score()
        return p1,p2,'%s wins!' % p1.get_name()
    
    elif m2 == m1 -1:
        p2.incr_score()
        return p1,p2,'%s wins!' % p2.get_name()
    
    else:
        return p1,p2,'draw: no winner'
    
    
## 在上面的函数中,调用了p1.get_move()和p2.get_move()
## 下面来实现这些函数

## 由于在游戏Undercut中,走法不过是选择1--10的数字
## 但是人类玩家是通过键盘键入一个1--10的数字,而计算机使用函数选择数字
## 因此 Human 和 Computer 类需要专用的get_move(self)方法

## 下面为Human类的方法 get_move

class Human(Player):
    def __repr__(self):
        return 'Human(%s)' % str(self)
    
    def get_move(self):
        while True:
            try:
                n = int(input('%s move (1 - 10):' % self.get_name()))
            
                if 1 <= n <= 10:
                    return n
                else:
                    print('Oops!')
            except:
                print('Oops!')
                
# 上面的功能就是要求用户一致输入时正确的1 -- 10 的整数为止
# try/except 结构用于捕获异常。

import random

class Computer(Player):
    def __repr__(self):
        return 'Computer(%s)' % str(self)
    
    def get_move(self):
        return random.randint(1,10)
    
## 代码基本上完成了,下面进行游戏的试玩

jisuanji = Computer('Hal Bot')
renlei = Human('lia')
play_undercut(jisuanji,renlei)

'''
    lia move (1 - 10):4
    Hal Bot move: 8
    lia move: 4

    (Computer(name = 'Hal Bot',score = 0),
     Human(name = 'lia',score = 0),
     'draw: no winner')

'''
最近更新时间:
Prev
OOP 面向对象:class