zoukankan      html  css  js  c++  java
  • python类与对象

    类与对象

    创建类

    通过关键字class创建一个Player类,来个栗子

    class Player:
        pass

    创建对象

    通过类实例化两个对象,来个栗子

    class Player:
        pass
    
    p1 = Player()
    p2 = Player()
    print(p1) #<__main__.Player object at 0x00000000020E2198>
    print(p2) #<__main__.Player object at 0x00000000020E2E48>

    添加属性

    举个栗子

    class Player:
        pass
    
    p1 = Player()
    p1.name = "tom"
    p1.lives = 3
    print(p1.name, p1.lives) #tom 3

    面向对象的重点在于不同对象之间的交互

    为类添加一些行为,当这些行为触发时,可以改变对象的属性,举个栗子

    class Player:
        def add_one_live(self):
            self.lives += 1
    
    p = Player()
    p.lives = 3
    p.add_one_live()
    print(p.lives) #4

    参数self

    self是对方法所调用对象的引用

    类中定义的函数,其第一个形参一般都要显示的传入self,否则在通过类实例调用函数时会报错

    class Player:
        def add_one_live():
            self.lives += 1
    
    p = Player()
    p.add_one_live() #TypeError: add_one_live() takes 0 positional arguments but 1 was given

    对象初始化

    python类对象的初始化一般包含两个部分:构造函数__new__和对象数据的初始化即初始化方法__init__,

    对象的创建是通过构造函数__new__,对象数据的初始化是通过初始化函数__init__,

    有的python内置类没有__init__方法,而直接在__new__方法中创建和初始化,如Tuple。

    class Player:
        def __init__(self, lives):
            self.lives = lives
    
        def add_one_live(self):
            self.lives += 1
    
    p = Player(3)
    print(p.lives) #3
    p.add_one_live()
    print(p.lives) #4

    文档注释

    可以在每个类、函数头定义语句的下一行添加字符串

    来个栗子

    class Player:
        'Represents a player in the game'
        def __init__(self, lives):
            self.lives = lives
    
        def add_one_live(self):
            """add one live
            when the player passed one game checkpoint"""
            self.lives += 1

    说明:python -i filename.py,加载这个文件到交互解释器中

       help(Player) 查看这个类的格式文档

    模块和包

    模块

    一个python文件就是一个模块

    模块的导入

    (1)导入整个模块, 在products.py模块需要实例化来自database.py模块中的Database类

    import database
    db = database.Database()

    (2)导入模块中的具体类

    from database import Database
    db = Database()

    (3)将导入的类重命名

    from database import Database as DB
    db = DB()

    (4)一次导入模块中的多个类

    from database import Database, Query

    (5)禁止使用import *

    from database import *

    说明:如果使用,将花费更多的时间去找出类的位置,丧失某些编辑器的代码自动补全,跳转到自定义类位置等功能

    一个包是一个目录下模块的集合,目录的名字就是包的名字,

    我们只需在目录下添加一个名为__init__.py的文件就可以告诉python这个目录是一个包

    taobao/
        main.py
        ecommerce/
            __init__.py
            database.py
            products.py
            contact/
                __init__.py
                email.py
            payments/
                __init__.py
                square.py
                stripe.py
                paypal.py

    来个栗子

    说明:目录中一共有3个包,在taobao这个目录下有1个ecommerce包,在ecommerce目录下有1个payments包和1个contact包

    绝对导入

    指定我们想要导入的模块或函数的完整路径,比如我们想要访问products模块中的Product类,可以用以下三种方法进行绝对导入

    import ecommerce.products
    product = ecommerce.products.Product()

    or

    from ecommercek.products import Product
    product = Product

    or

    from ecommerce import products
    product = products.Product()

    说明:这些语句可以在taobao目录下的任何模块中运行

     如果products模块下有10个左右的类是我需要使用的,通常使用第三种方法导入

    如果products模块下只有2个类是我需要的,通常使用第二种方法导入

    相对导入

    应用1,寻找与当前模块在位置上有相对关系的类或函数,比如我们想在products模块中导入与之相邻的database模块中的Database类

    from .database import Database

    点号表示使用当前包内的database模块,即ecommerce包

    应用2,如果我们要在paypal模块中使用父包中的database模块,可以用两点号来实现

    from ..database import Database

    当然,我们也可以利用更多的点来导入更高层级包中的模块,也可以一边后退回到其他较深层

    应用3,比如,我们想在paypal模块中使用contact包下的email模块中的send_email函数

    from ..contact.email import send_email

    说明:..contact.email用了两个点号回到了payments包的上一层,然后用正常的package.module语法回到了contact包那一层

    我们也可以从包中导入代码

    应用4,比如,database模块中有一个变量db,会有从许多不同的包来访问,import ecommerace.db显然比import ecommerce.database.db更方便

    在我们的例子中,如果ecommerce/__init__.py中包含如下一行代码

    from .database import db

    那么我们可以在main.py和其他任何文件中直接访问ecommerce包中的db属性

    from ecommerce import db

    __init__.py文件是与其他模块通信的主要节点,但是代码可以在内部组织为几个不同的模块或子包。

    组织模块

    栗子1,如果我们想要在多个模块中导入Database类并进行实例化,我们可以在多个模块中导入类DataBase并进行实例化,

    但是更为合理的做法是只有一个全局的Database实例对象,database.py模块代码如下

    class Database:
        pass
    
    database = Database()

    分析

    但是这存在一个问题,由于模块中调用的代码都会在导入时立即执行,当我们在对database.py模块导入时,Database实例对象就立即被创建,

    这通常发生在程序启动时,而数据库的连接又需要时间,这会增加程序启动的时间。

    那我们怎么办?当然来推迟Database对象实例的创建时间。

    class Database:
        pass
    
    database = None
    
    def init_database():
        global database
        database = Database()

    栗子2,一个程序的main.py模块,需要从其他程序中的模块中导入某些函数或类,然而一旦导入,所有这些模块层的代码都会立即执行,

    但是我们只想访问其中的几个函数。

    分析:为了解决这一问题,我们可以将启动的代码放到一个函数中,一般叫main,只有模块作为脚本运行时才执行这一函数。

    class Util:
        pass
    
    def main():
        util = Util()
        print(util)
        pass
    
    if __name__ == '__main__':
        main()

    说明:将所有的脚本代码包含在if __name__ == '__main__':下,以防止你写的函数被其他的代码导入。

    方法定义在类中,类定义在模块中,模块存在于包中。

    说明:这是python一种典型的顺序,类可以定义在任何地方如定义在一个函数的内部,这通常用于一次性对象。 

    参考资料:《python3面向对象编程》

  • 相关阅读:
    第一章-环境准备
    selenium-pageobject设计模式
    自动化测试用例设计原则
    selenium隔离环境安装、以及示例
    json extractor获取返回值中动态新增的数据
    jmeter返回值乱码问题
    liunx命令
    SQL表结构语句
    测试网络脚本python
    C# 订单流水号生成
  • 原文地址:https://www.cnblogs.com/marton/p/10848425.html
Copyright © 2011-2022 走看看