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面向对象编程》

  • 相关阅读:
    PAT 甲级 1115 Counting Nodes in a BST (30 分)
    PAT 甲级 1114 Family Property (25 分)
    PAT 甲级 1114 Family Property (25 分)
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
  • 原文地址:https://www.cnblogs.com/marton/p/10848425.html
Copyright © 2011-2022 走看看