python基础(类、对象、包)完整的总结

  • 内容
  • 相关

python基础(类和对象、包)

类和对象

对象是看的见摸的着的

类是模板

对象需要类才能创建出来

类的构成(三个部分)

类的名称:类名

类的属性:一组数据

类的方法:允许进行操作的方法(行为)

class 类名():

def

添加方法

class Cat():

    def run(self):

        print(“cat is running”)

xiaobai = Cat()

xiaobai.run()

xiaobai.name = “小白”

xiaobai.age = 40

类的属性

属性就是变量

一个类可以创建多个对象

注意self

class Cat():

    def intro(self):

        print(“%s%d” % (self.name, self.age))

    def run(self):

        print(“cat is running”)

xiaobai = Cat()

xiaobai.run()

xiaobai.name = “小白”

xiaobai.age = 40

xiaobai.intro()

两个对象的时候就要注意self

__init__ 方法 魔法方法

创建对象的过程

1.创建一个对象

2.自动的调用__init__方法

3.返回创建的对象的引用

def __init__(self,new_name,new_age):

    self.name = new_age

    self.age = new_age

传入

xiaobai = Cat(“lammao”,40)

new_age

new_name 是局部变量

__str__方法

当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据

隐藏对象的属性

将属性定义为私有属性,外部调用不了 加上__

私有方法

在方法前面加上__

在一个类的里面调用其他方法

self+方法名

__del__方法

del可以删除对象

当删除一个对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法

class Dog:

   def __del__(self):

       print(“死啦”)

dog = Dog

dog1 = Dog

del dog  #此时不调用del方法 这个对象有别的变量指向

del dog1 #此时调用

如果在程序结束的时候,有些对象还存在,python解释器自动调用del方法完成清理工作

import random

工具箱

import sys

sys.getrefcount(对象名)

可以查看有几个变量指向这个对象引用的个数 比实际个数大1

继承

class Animal():

    pass

clss Dog(Animal):

    pass

父类的功能子类可以直接用

几个子类 的方法不知调用

父类,子类的方法还可以被子类的子类的调用

重写

父类的方法可以在子类中从新写

调用从写的方法和原有的方法

1.父类名.方法名(slef)

2.super().重复的方法名()

私有方法,私有属性的表现(不会被继承)

父类的私有方法私有属性不能直接在子类用

如果调用的是继承父类中的公有方法 可以在这个公有方法中访问父类中的私有方法和私有属性

如果在子类中实现一个公有方法,那么在这个方法中是不能调用继承的父类中的私有方法和私有属性

多继承

没有继承别的类,可以在后面写上(object)写上成为新式类

不写 就叫做经典类

继承多个类 写在括号中()

c3算法

类名.__mro__

决定这调用一个方法的时候,搜索的顺序,如果在某个类中找到了方法,就停止搜索

多态

当你调用一个方法,不知道调用是子类还是父类

直到调用的时候 才能发现调用的子类父类

class Dog(object):

    def print_self(self):

        print(“大家好,我是xxx,希望大家多多关照”)

class xiaotq(Dog):

    def print_self(self):

        print(“hello,everybody”)

def introduce(temp):

    temp.print_self()

dog1 = Dog()

dog2 = xiaotq()

introduce(dog1)

introduce(dog2)

类属性和实例属性

如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。

@classmethod类方法 和实例方法

@staticmethod静态方法

__new__ 方法

class A(object):

    def __init__(self):

        print(“这是init 方法”)

    def __new__(cls):

        print(“这是 new 方法”)

        return object.__new__(cls)

A()

注意:

__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供

__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例

__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

我们可以将类比作制造商,__new__方法就是前期的原材料购买环节,__init__方法就是在有原材料的基础上,加工,初始化商品环节

单例模式

1.确保某一个类只有一个实例,而且自行实例化并向震哥哥系统提供这个实例,这个类成为单例类,单例模式是一种对象创建型模式。

回收站就是单例模式的应用

2.创建单例 要保证只有一个对象

3.创建单例时 只执行一次__init__方法

异常处理

try:

expect :

eg.try:

        print(‘—–test–1—‘)

        open(‘123.txt’,’r’)

        print(‘—–test–2—‘)

   except IOError:

        pass

ecpect 捕捉多个异常

获取异常信息的描述

try except eles

try…finally…语句用来表达这样的情况:

在程序中,如果一个段代码必须要执行,即无论异常是否产生都要执行,那么此时就需要使用finally。 比如文件关闭,释放锁,把数据库连接返还给连接池等

demo:

import time

try:

    f = open(‘test.txt’)

    try:

        while True:

            content = f.readline()

            if len(content) == 0:

                break

            time.sleep(2)

            print(content)

    except:

        #如果在读取文件的过程中,产生了异常,那么就会捕获到

        #比如 按下了 ctrl+c

        pass

    finally:

        f.close()

        print(‘关闭文件’)

except:

    print(“没有这个文件”)

我们可以观察到KeyboardInterrupt异常被触发,程序退出。但是在程序退出之前,finally从句仍然被执行,把文件关闭。

try嵌套

import time

try:

    f = open(‘test.txt’)

    try:

        while True:

            content = f.readline()

            if len(content) == 0:

                break

            time.sleep(2)

            print(content)

    finally:

        f.close()

        print(‘关闭文件’)

except:

    print(“没有这个文件”)

运行结果:

In [26]: import time

    …: try:

    …:     f = open(‘test.txt’)

    …:     try:

    …:         while True:

    …:             content = f.readline()

    …:             if len(content) == 0:

    …:                 break

    …:             time.sleep(2)

    …:             print(content)

    …:     finally:

    …:         f.close()

    …:         print(‘关闭文件’)

    …: except:

    …:     print(“没有这个文件”)

    …: finally:

    …:     print(“最后的finally”)

    …:

xxxxxxx—>这是test.txt文件中读取到信息

^C关闭文件

没有这个文件

最后的finally

函数嵌套调用中

import time

try:

    f = open(‘test.txt’)

    try:

        while True:

            content = f.readline()

            if len(content) == 0:

                break

            time.sleep(2)

            print(content)

    finally:

        f.close()

        print(‘关闭文件’)

except:

    print(“没有这个文件”)

运行结果:

In [26]: import time

    …: try:

    …:     f = open(‘test.txt’)

    …:     try:

    …:         while True:

    …:             content = f.readline()

    …:             if len(content) == 0:

    …:                 break

    …:             time.sleep(2)

    …:             print(content)

    …:     finally:

    …:         f.close()

    …:         print(‘关闭文件’)

    …: except:

    …:     print(“没有这个文件”)

    …: finally:

    …:     print(“最后的finally”)

    …:

xxxxxxx—>这是test.txt文件中读取到信息

^C关闭文件

没有这个文件

最后的finally

2. 函数嵌套调用中

    def test1():

        print(“—-test1-1—-“)

        print(num)

        print(“—-test1-2—-“)

    def test2():

        print(“—-test2-1—-“)

        test1()

        print(“—-test2-2—-“)

    def test3():

        try:

            print(“—-test3-1—-“)

            test1()

            print(“—-test3-2—-“)

        except Exception as result:

            print(“捕获到了异常,信息是:%s”%result)

        print(“—-test3-2—-“)

    test3()

    print(“——华丽的分割线—–“)

    test2()

如果try嵌套,那么如果里面的try没有捕获到这个异常,那么外面的try会接收到这个异常,然后进行处理,如果外边的try依然没有捕获到,那么再进行传递。。。

如果一个异常是在一个函数中产生的,例如函数A—->函数B—->函数C,而异常是在函数C中产生的,那么如果函数C中没有对这个异常进行处理,那么这个异常会传递到函数B中,如果函数B有异常处理那么就会按照函数B的处理方式进行执行;如果函数B也没有异常处理,那么这个异常会继续传递,以此类推。。。如果所有的函数都没有处理,那么此时就会进行异常的默认处理,即通常见到的那样

注意观察上图中,当调用test3函数时,在test1函数内部产生了异常,此异常被传递到test3函数中完成了异常处理,而当异常处理完后,并没有返回到函数test1中进行执行,而是在函数test3中继续执行

class Test(object):

    def __init__(self, switch):

        self.switch = switch #开关

    def calc(self, a, b):

        try:

            return a/b

        except Exception as result:

            if self.switch:

                print(“捕获开启,已经捕获到了异常,信息如下:”)

                print(result)

            else:

                #重新抛出这个异常,此时就不会被这个异常处理给捕获到,从而触发默认的异常处理

                raise

a = Test(True)

a.calc(11,0)

print(“———————-华丽的分割线—————-“)

a.switch = False

a.calc(11,0)

模块

<1>Python中的模块

有过C语言编程经验的朋友都知道在C语言中如果要引用sqrt函数,必须用语句#include <math.h>引入math.h这个头文件,否则是无法正常进行调用的。

那么在Python中,如果要引用一些其他的函数,该怎么处理呢?

在Python中有一个概念叫做模块(module),这个和C语言中的头文件以及Java中的包很类似,比如在Python中要调用sqrt函数,必须用import关键字引入math这个模块,下面就来了解一下Python中的模块。

说的通俗点:模块就好比是工具包,要想使用这个工具包中的工具(就好比函数),就需要导入这个模块

<2>import

在Python中用关键字import来引入某个模块,比如要引用模块math,就可以在文件最开始的地方用import math来引入。

形如:

    import module1,mudule2…

当解释器遇到import语句,如果模块在当前的搜索路径就会被导入。

在调用math模块中的函数时,必须这样引用:

  模块名.函数名

想一想:

为什么必须加上模块名调用呢?

答:

因为可能存在这样一种情况:在多个模块中含有相同名称的函数,此时如果只是通过函数名来调用,解释器无法知道到底要调用哪个函数。所以如果像上述这样引入模块的时候,调用函数必须加上模块名

    import math

    #这样会报错

    print sqrt(2)

    #这样才能正确输出结果

    print math.sqrt(2)

有时候我们只需要用到模块中的某个函数,只需要引入该函数即可,此时可以用下面方法实现:

    from 模块名 import 函数名1,函数名2….

不仅可以引入函数,还可以引入一些全局变量、类等

注意:

通过这种方式引入的时候,调用函数时只能给出函数名,不能给出模块名,但是当两个模块中含有相同名称函数的时候,后面一次引入会覆盖前一次引入。也就是说假如模块A中有函数function( ),在模块B中也有函数function( ),如果引入A中的function在先、B中的function在后,那么当调用function函数的时候,是去执行模块B中的function函数。

如果想一次性引入math中所有的东西,还可以通过from math import *来实现

<3>from…import

Python的from语句让你从模块中导入一个指定的部分到当前命名空间中

语法如下:

    from modname import name1[, name2[, … nameN]]

例如,要导入模块fib的fibonacci函数,使用如下语句:

    from fib import fibonacci

注意

不会把整个fib模块导入到当前的命名空间中,它只会将fib里的fibonacci单个引入

<4>from … import *

把一个模块的所有内容全都导入到当前的命名空间也是可行的,只需使用如下声明:

    from modname import *

注意

这提供了一个简单的方法来导入一个模块中的所有项目。然而这种声明不该被过多地使用。

<5> as

    In [1]: import time as tt

    In [2]: time.sleep(1)

    —————————————————————————

    NameError                                 Traceback (most recent call last)

    <ipython-input-2-07a34f5b1e42> in <module>()

    —-> 1 time.sleep(1)

    NameError: name ‘time’ is not defined

    In [3]:

    In [3]:

    In [3]: tt.sleep(1)

    In [4]:

    In [4]:

    In [4]: from time import sleep as sp

    In [5]: sleep(1)

    —————————————————————————

    NameError                                 Traceback (most recent call last)

    <ipython-input-5-82e5c2913b44> in <module>()

    —-> 1 sleep(1)

    NameError: name ‘sleep’ is not defined

    In [6]:

    In [6]:

    In [6]: sp(1)

    In [7]:

<6>定位模块

当你导入一个模块,Python解析器对模块位置的搜索顺序是:

当前目录

如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。

如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/

模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。

自定义模块的调用

test.py

def add(a,b)

    return a+b

调用方法

import test

form test import add

如果一个文件中有__all__变量,那么也就意味着这个变量中的元素,不会被from xxx import *时导入

模块安装、使用

1.安装的方式

找到模块的压缩包

解压

进入文件夹

执行命令python setup.py install

注意:

如果在install的时候,执行目录安装,可以使用python setup.py install –prefix=安装路径

2.模块的引入

在程序中,使用from import 即可完成对安装的模块使用

from 模块名 import 模块名或者*

python中的包

1. 引入包

1.1 有2个模块功能有些联系

1.2 所以将其放到同一个文件夹下

1.3 使用import 文件.模块 的方式导入

1.4 使用from 文件夹 import 模块 的方式导入

1.5 在msg文件夹下创建__init__.py文件

1.6 在__init__.py文件中写入

1.7 重新使用from 文件夹 import 模块 的方式导入

总结:

包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为__init__.py 文件,那么这个文件夹就称之为包

有效避免模块名称冲突问题,让应用组织结构更加清晰

2. __init__.py文件有什么用

__init__.py 控制着包的导入行为

2.1 __init__.py为空

仅仅是把这个包导入,不会导入包中的模块

2.2 __all__

在__init__.py文件中,定义一个__all__变量,它控制着 from 包名 import *时导入的模块

2.3 (了解)可以在__init__.py文件中编写内容

可以在这个文件中编写语句,当导入时,这些语句就会被执行

__init__.py文件

3. 扩展:嵌套的包

假定我们的包的例子有如下的目录结构:

Phone/

    __init__.py

    common_util.py

    Voicedta/

        __init__.py

        Pots.py

        Isdn.py

    Fax/

        __init__.py

        G3.py

    Mobile/

        __init__.py

        Analog.py

        igital.py

    Pager/

        __init__.py

        Numeric.py

Phone 是最顶层的包,Voicedta 等是它的子包。 我们可以这样导入子包:

import Phone.Mobile.Analog

Phone.Mobile.Analog.dial()

你也可使用 from-import 实现不同需求的导入

第一种方法是只导入顶层的子包,然后使用属性/点操作符向下引用子包树:

from Phone import Mobile

Mobile.Analog.dial(‘555-1212’)

此外,我们可以还引用更多的子包:

from Phone.Mobile import Analog

Analog.dial(‘555-1212’)

事实上,你可以一直沿子包的树状结构导入:

from Phone.Mobile.Analog import dial

dial(‘555-1212’)

在我们上边的目录结构中,我们可以发现很多的 __init__.py 文件。这些是初始化模块,from-import 语句导入子包时需要用到它。 如果没有用到,他们可以是空文件。

包同样支持 from-import all 语句:

from package.module import *

然而,这样的语句会导入哪些文件取决于操作系统的文件系统。所以我们在__init__.py 中加入 __all__ 变量。该变量包含执行这样的语句时应该导入的模块的名字。它由一个模块名字符串列表组成.


原文地址:http://www.ldxzs.top/2018/06/26/python%E5%9F%BA%E7%A1%80%E7%B1%BB%E5%92%8C%E5%AF%B9%E8%B1%A1%E3%80%81%E5%8C%85/

本文标签:

版权声明:若无特殊注明,本文皆为《秋白》原创,转载请保留文章出处。

本文链接:python基础(类、对象、包)完整的总结 - https://www.jqlab.cn/post-805.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注