Python语法

 
 
 

python pip

pipy国内镜像目前有:

http://pypi.douban.com/  豆瓣

http://pypi.hustunique.com/  华中理工大学

http://pypi.sdutlinux.org/  山东理工大学

http://pypi.mirrors.ustc.edu.cn/  中国科学技术大学

  

从指定源安装:pip install 模块名 -i https://pypi.douban.com/simple (注意后面要有/simple目录)

pip install cchardet #不指定版本号,安装可用的最新版本(版本范围符号:==、>=、<=、>、<。)
pip install -v requests==2.7 #指定版本号2.7
pip install -v requests>2.0,<3.0 #(2.0,3.0)之间的最新版本

显示安装包信息:pip show 模块名
显示安装包信息:pip show -f 包名
列出已安装的包:pip list
搜索包:pip search 模块名
卸载包:pip uninstall 模块名
查看可升级的包:pip list -o
升级包:pip install --U 模块名
升级所有包:pip-review --local --interactive (借助模块pip-review pip install pip-review)

 

依赖包清单

使用pipreqs为当前的Python项目生成所有依赖包的清单requirements .txt
# 安装
pip install pipreqs

#装好之后cmd到项目路径下,在项目根目录下执行
pipreqs ./ --encoding=utf8 --force     #--encoding=utf8 为使用utf8编码,不然可能会报错。--force 强制执行,当生成目录下的requirements.txt存在时覆盖。

或者直接用python生成。  generate_lib.py

1
2
3
4
5
6
import os
 
new_path=os.path.dirname(__file__)
os.chdir(new_path)
 
os.system(f'pipreqs ./ --encoding=utf8 --force')

使用requirements.txt安装依赖的方式:
pip install -r requirements.txt

也可以用python安装。install_lib.py

1
2
3
4
5
6
7
import os
 
new_path=os.path.dirname(__file__)
os.chdir(new_path)
 
#指定阿里源进行安装
os.system('pip install -r requirements.txt -i  https://mirrors.aliyun.com/pypi/simple')

  

批量卸载安装包

pip uninstall -y -r requirements.txt   #批量静默卸载,即不用回答yes

 

查看所有的关键字: help("keywords")
查看系统中所有的模块(包括自带和第三方):help('modules')
查看某模块说明: help("XXX")
查看某模块的属性和方法: dir(XXX)
查看系统内置内的属性和方法: dir(__builtins__) / dir(builtins)

用双下划线开头且结尾的变量,在 Python 中被称为内置变量,常见的有如下:
__file__ 获取当前运行的py文件所在的目录
__doc__ 函数、或者文档的注释
__package__ 输出对应函数属于哪个包 . admin.__package__
__name____若是在当前文件,__name__ 是__main__。若是导入的文件,__name__是模块名。
__all__ 结果是一个列表,存储的是当前模块中一些成员(变量、函数或者类)的名称。

编码

Windows系统默认的编码是gbk,对于支持 Unicode的应用程序,Windows 会默认使用 Unicode编码。对于不支持Unicode的应用程序Windows 会采用 ANSI编码 (也就是各个国家自己制定的标准编码方式,如对于西欧文字有ISO/IEC 8859编码,对于简体中文有GB 18030编码,对于繁体中文有BIG-5等),Windows对于不支持Unicode的程序默认只能使用一种ANSI编码

Unicode定义了所有可以用来表示字符的数值集合。Unicode同ascii一样是一种编码方式。UTF标准定义了这些数值和字符的映射关系,是一种存储方式(格式)。Unicode用2个字节表示一个字符,Unicode是用0至65535之间的数字来表示所有字符,其中0至127这128个数字表示的字符仍然跟ASCII完全一样。但65536显然不太不够,于是从1996年开始又来了Unicode2,Unicode2用4个字节表示所有字符。

Unicode 可以使用的编码有三种,分别是:
UFT-8:一种变长的编码方案,使用 1-4个字节来存储;
UTF-16:长度既固定又可变,使用 2 个或者 4 个字节来存储,UTF-16直接就是unicode编码, 没有变换。
UFT-32:一种固定长度的编码方案,不管字符编号大小,始终使用 4 个字节来存储;

只有UTF-8兼容ASCII,UTF-32和UTF-16都不兼容ASCII,因为它们没有单字节编码。如果Unicode字符由2个字节表示,则编码成UTF-8很可能需要3个字节。而如果Unicode字符由4个字节表示,则编码成UTF-8可能需要6个字节。

在ASCII码中,一个汉字占2个字节,一个英文字符占一个字节。在Unicode编码中,一个汉字占2个字节,一个英文字符占两个字节

f = open("c:/xx.txt",'r',encoding='utf-8')#encoding='utf-8'是用来指明被读取文件的编码格式的,如果被读取文件是中文的且没有指明其编码,python会默认其编码为gbk,此时读取文件内容会出错。读取文件时声明编码格式,使用encoding='xxx';文件是ansi编码时可以不用指定编码格式。

 

模块

模块名全部小写,对于包内使用的模块,可以加一个下划线前缀,如

module.py

_internal_module.py

在程序的开发过程中,随着程序代码越写越多,在一个文件里代码会越来越不容易维护。为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少。在Python中一个.py文件就称之为一个模块(Module)。模块也被叫做库。

 

模块用来从逻辑上组织Python代码,是.py结尾的python文件。包用来从逻辑上组织模块的,包和一般的文件夹没什么区别,关键是包文件夹下必须包含一个__init__.py,表明这是一个包。包的命名规范与模块相同。

 函数---->类---->模块(.py文件)---->包

 

模块的安装

方法1:单文件模块

直接把文件拷贝到 $python_dir/Lib

 

方法2:多文件模块,带setup.py

下载模块包进行解压,进入模块文件夹,执行:
python setup.py install

setup.py文件的编写(setup.py中主要执行一个 setup函数。可网上查找。)

 

 

导入模块

1、python调用模块的步骤:

1) 检索可用路径

2)根据路径的优先级来查找模块,其中当前路径的优先级最高

由此可知要使我们的模块可以被python检索到,模块就必须放在可用路径内

1)\lib\site-packages为标准化的第三方模块存放路径。

2)可将将自己写的exp.py 文件放到sys.path列表中的目录里(如site-packages目录),使用时采用 import exp 导入。

 

2、导入

import module 导入模块,推荐import来去导入因为这样可以使你的程序更加易读,也可以避免名称的冲突
import module1,module2 导入多个模块
from module import * 从模块导入所有方法,采用该方式则可在代码中直接使用方法名。
from packs import hello 从包中导入模块

 

3、同级目录下的调用

--file
   |--test1.py
   |--test2.py

若在程序test2.py中导入模块test1, 则直接使用

import test1
test1.fun1()
#或
from test1 import fun1
fun1()

 

4、调用子目录

--file
    |--top.py
    |--lib
       |--mod1.py

要在top.py中导入模块mod1.py :

from lib import mod1
mod1.fun()

 

5、子目录调用

--file
    |--top.py
    |--lib
       |--mod1.py

要在mod1.py 中导入模块top.py的test1 :

import os,sys
sys.path.append(os.path.dirname(os.path.dirname(__file__))) #将上级目录加入
from top import test1

 

6、跨目录调用

file0
   |--file1
      |--test1.py
   |--file2
      |--test2.py

现在要在test2.py中导入test1.py的模块,需要增加调用文件的目录,可以是相对路径也可以是绝对路径。

import os,sys
sys.path.append(os.path.dirname(os.path.dirname(__file__))) #将上级目录加入
from file1 import test1

 

 

print用法

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

  • objects -- 复数,表示可以一次输出多个对象。输出多个对象时,需要用 , 分隔。
  • sep -- 用来间隔多个对象,默认值是一个空格。
  • end -- 用来设定以什么结尾。默认值是换行符 \n,我们可以换成其他字符串。
  • file -- 要写入的文件对象。
  • flush -- 输出是否被缓存通常决定于 file,但如果 flush 关键字参数为 True,流会被强制刷新。

print()会依次打印每个字符串,遇到逗号“,”会输出一个空格。
print会输出一个\n,也就是换行符,这样光标移动到了下一行行首,接着输出。

\r ---回车,光标重新回到本行开头,控制字符可以写成CR
\n---换行,光标往下一行(不一定到下一行行首),控制字符可以写成LF
\t---制表符,即tab键,输出两个或4个空格(python)
\b---退格,即backspace删除键

windows的换行并回到行首是\r\n,unix的是\n,mac的是\n。

 

没有括号的就是返回了对函数fun的引用, 带括号的fun() 指的是对函数求值的结果
Python对大小写十分敏感,如果大小写错误,会报错
break意思为结束整个循环
continue意思为结束当前循环进入下一个循环
return 结束程序

 

 

Python逻辑运算

Python语言支持逻辑运算符,以下假设变量 a 为 10, b为 20:

运算符

逻辑表达式

描述

实例

and

x and y

布尔"与" - 如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值。

(a and b) 返回 20。

or

x or y

布尔"或" - 如果 x 是非 0,它返回 x 的计算值,否则它返回 y 的计算值。

(a or b) 返回 10。

not

not x

布尔"非" - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。

not(a and b) 返回 False

 

Python成员运算

除了以上的一些运算符之外,Python还支持成员运算符,测试实例中包含了一系列的成员,包括字符串,列表或元组。

运算符

描述

实例

in

如果在指定的序列中找到值返回 True,否则返回 False。

x 在 y 序列中 , 如果 x 在 y 序列中返回 True。

not in

如果在指定的序列中没有找到值返回 True,否则返回 False。

x 不在 y 序列中 , 如果 x 不在 y 序列中返回 True。

 

Python位运算

按位运算符是把数字看作二进制来进行计算的。Python中的按位运算法则如下:

下表中变量 a 为 60,b 为 13,二进制格式如下:

a = 0011 1100

b = 0000 1101

-----------------

a&b = 0000 1100

a|b = 0011 1101

a^b = 0011 0001

~a  = 1100 0011

运算符

描述

实例

&

按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0

(a & b) 输出结果 12 ,二进制解释: 0000 1100

|

按位或运算符:只要对应的二个二进位有一个为1时,结果位就为1。

(a | b) 输出结果 61 ,二进制解释: 0011 1101

^

按位异或运算符:当两对应的二进位相异时,结果为1

(a ^ b) 输出结果 49 ,二进制解释: 0011 0001

~

按位取反运算符:对数据的每个二进制位取反,即把1变为0,把0变为1 。~x = -x+1

(~a ) 输出结果 -61 ,二进制解释: 1100 0011,在一个有符号二进制数的补码形式。

<< 

左移动运算符:运算数的各二进位全部左移若干位,由 << 右边的数字指定了移动的位数,高位丢弃,低位补0。

a << 2 输出结果 240 ,二进制解释: 1111 0000

>> 

右移动运算符:把">>"左边的运算数的各二进位全部右移若干位,>> 右边的数字指定了移动的位数

a >> 2 输出结果 15 ,二进制解释: 0000 1111

 

异常

首先,执行try子句,如果没有异常发生,忽略except子句,try子句执行结束。如果在执行try子句的过程中发生了异常,那么try子句余下的部分将被忽略。如果异常的类型和 except 之后的名称相符,那么对应的except子句将被执行。最后执行 try 语句之后的代码。如果一个异常没有与任何的except匹配,那么这个异常将会传递给上层的try中。

 

 

异常

ptyhon的错误其实也是 class,所有的错误类型都继承自BaseException,所以在使用except时需要注意的是,它不但捕获该类型的错误,还把其子类也“一网打尽”。

BaseException 所有异常的基类

 +-- SystemExit 解释器请求退出

 +-- KeyboardInterrupt 用户中断执行(通常是输入^C)

 +-- GeneratorExit 生成器(generator)发生异常来通知退出

 +-- Exception 常规错误的基类

      +-- StopIteration 迭代器没有更多的值

      +-- StopAsyncIteration

      +-- ArithmeticError 所有数值计算错误的基类

      |    +-- FloatingPointError 浮点计算错误

      |    +-- OverflowError 数值运算超出最大限制

      |    +-- ZeroDivisionError (或取模)(所有数据类型)

      +-- AssertionError 断言语句失败

      +-- AttributeError 对象没有这个属性

      +-- BufferError

      +-- EOFError  没有内建输入,到达EOF 标记

      +-- ImportError 导入模块/对象失败

      |    +-- ModuleNotFoundError

      +-- LookupError 无效数据查询的基类

      |    +-- IndexError 序列中没有此索引(index)

      |    +-- KeyError 映射中没有这个键

      +-- MemoryError 内存溢出错误(对于Python 解释器不是致命的)

      +-- NameError 未声明/初始化对象 (没有属性)

      |    +-- UnboundLocalError 访问未初始化的本地变量

      +-- OSError 输入/输出操作失败

      |    +-- BlockingIOError

      |    +-- ChildProcessError

      |    +-- ConnectionError

      |    |    +-- BrokenPipeError

      |    |    +-- ConnectionAbortedError

      |    |    +-- ConnectionRefusedError

      |    |    +-- ConnectionResetError

      |    +-- FileExistsError

      |    +-- FileNotFoundError

      |    +-- InterruptedError

      |    +-- IsADirectoryError

      |    +-- NotADirectoryError

      |    +-- PermissionError

      |    +-- ProcessLookupError

      |    +-- TimeoutError

      +-- ReferenceError 弱引用(Weak reference)试图访问已经垃圾回收了的对象

      +-- RuntimeError  一般的运行时错误

      |    +-- NotImplementedError 尚未实现的方法

      |    +-- RecursionError

      +-- SyntaxError Python语法错误

      |    +-- IndentationError 缩进错误

      |         +-- TabError Tab 和空格混用

      +-- SystemError 一般的解释器系统错误

      +-- TypeError 对类型无效的操作

      +-- ValueError 传入无效的参数

      |    +-- UnicodeError Unicode 相关的错误

      |         +-- UnicodeDecodeError Unicode 解码时的错误

      |         +-- UnicodeEncodeError Unicode 编码时错误

      |         +-- UnicodeTranslateError Unicode 转换时错误

      +-- Warning 警告的基类

           +-- DeprecationWarning 关于被弃用的特征的警告

           +-- PendingDeprecationWarning 关于特性将会被废弃的警告

           +-- RuntimeWarning 可疑的运行时行为(runtime behavior)的警告

           +-- SyntaxWarning 可疑的语法的警告

           +-- UserWarning 用户代码生成的警告

           +-- FutureWarning 关于构造将来语义会有改变的警告

           +-- ImportWarning

           +-- UnicodeWarning

           +-- BytesWarning

           +-- ResourceWarning

 

 

 

一、类概述

面向对象重要的概念就是类(Class)和实例(Instance),类是抽象的模板,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。类可以起到模板的作用,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的init方法,在创建实例的时候,就把属性绑上去。传递给类的函数都是由类的构造函数来处理的。与类和实例无绑定关系的function都属于函数(function);与类和实例有绑定关系的function都属于方法(method)。

(1)、__init__方法的第一参数永远是self,表示创建的类实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。

(2)、有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传。这里self就是指类本身。

(3)、和普通数相比,在类中定义的函数第一参数永远是类的本身实例变量self,并且调用时,不用传递该参数。除此之外,类的方法(函数)和普通函数没啥区别。

(4)、如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线,就变成了一个私有变量(private)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Person():
    def __init__(self):
        self.eyes = "眼睛"
        self.nose = "鼻子"
        self.mouth = "嘴巴"
 
kele1 = Person()
kele2 = Person()
print(kele1)
print(kele2)<br>
'''
<__main__.Person object at 0x0000018E1BBCCE50>
<__main__.Person object at 0x0000018E1BC39910>
'''

在默认情况下类创建出来的各个对象都是不一样的,如果我们想一个类创建出来的对象都是一样的,那就需用到 new 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Person():
    instance = None
    def __new__(cls, *args, **kwargs):
        if not cls.instance:
            cls.instance = super(Person, cls).__new__(cls, *args, **kwargs)
        return cls.instance
 
    def __init__(self):
        self.eyes = "眼睛"
        self.nose = "鼻子"
        self.mouth = "嘴巴"
 
kele1 = Person()
kele2 = Person()
print(kele1)
print(kele2)<br>
'''
<__main__.Person object at 0x000002BFC93E1520>
<__main__.Person object at 0x000002BFC93E1520>
'''

二、类的属性

1、直接定义在类体中的属性叫类属性,而在类的方法中定义的属性叫实例属性。
2、类数据属性属于类本身,可以通过类名进行访问/修改;
3、类数据属性也可以被类的所有实例访问/修改;
4、在类定义之后,可以通过类名动态添加类数据属性,新增的类属性也被类和所有实例共有;
5、实例数据属性只能通过实例访问;
6、在实例生成后,还可以动态添加实例数据属性,但是这些实例数据属性只属于该实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Student(object):
  
    count = 0
    books = []
    sex = 'man'
  
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
    def initStuff(self):
        self.x = 88
 
print(Student.sex) #man  Student可以访问自身属性
Student.sex='women'
print(Student.sex) #women Student可以修改自身属性
 
print(Student.x)    # Student不能访问和修改name、age、x,他们是实例属性
Student.initStuff() # Student不能访问方法。若要可以访问需方法为类方法,即@classmethod所修饰的方法
 
#实例1
tester=Student('TTT',23)
 
print(tester.name)#TTT
 
tester.sex='none'
print(tester.sex) #none 实例可以访问和修改类属性,但改的不是类属性本身,而是实例属性这个拷贝
 
tester.name='uuu'
print(tester.name)#uuu
 
#实例2
dever=Student('SSS',26)
print(dever.sex) #women 实例可以访问和修改类属性

通过内建函数dir(),或者访问类的字典属性__dict__,这两种方式都可以查看类或者实例有哪些属性。

__xxx__ 表示特殊变量,一种约定用来表示Python内部的名字,可以直接访问,我们自己的变量一般不要用这种方式
__xxx 表示是私有变量,外部不能访问
_xxx 表示外部是可以访问,但按照约定俗成的规定应将其视为私有变量,不随意访问,方法或属性不会被 from module import * 导入。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Student(object):
 
    def __init__(self, name, score,age):
        self.__name = name
        self.__score = score
        self.age = age
 
    def print_score(self):
        print(f"{self.__name}:{self.__score}")
 
student = Student('Hugh', 99,23)<br>
print(student.age) #23
print(student.__name) #__name是私有实例属性,在外部不能访问

如果外部代码要获取或修改name和score怎么办?可以给Student类增加get_name和get_score这样的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Student(object):
 
    def __init__(self, name, score,age):
        self.__name = name
        self.__score = score
        self.age = age
 
    #使外部代码可访问__name
    def get_name(self):
        return self.__name
     
    #使外部代码可访问__score
    def get_score(self):
        return self.__score
 
    #使外部代码可修改__score
    def set_score(self, score):
        self.__score = score
 
#实例
student = Student('Hugh', 88,23)<br>
print(student.age) #23
print(student.get_name())#Hugh
 
student.set_score(100)
print(student.get_score())#100

三、类的方法

python的面向对象中有3种类型的方法:实例方法、类方法、静态方法。

  • 类方法:传递的是类名而非对象。该方法的第一个参数是类名,调用时也需要指定类。类方法和静态方法只能操作类属性。
  • 静态方法:不通过self传递。一般如果一个方法不需要用到self,那么它就适合用作静态方法。静态方法其实和普通的方法一样,只不过在调用的时候需要使用类或者实例。之所以需要静态方法,是因为有时候需要将一组逻辑上相关的函数放在一个类里面,便于组织代码结构。
  • 实例方法:通过self参数传递实例对象自身。在类里每次定义实例方法的时候都需要指定实例(该方法的第一个参数,名字约定成俗为self)。这是因为实例方法的调用离不开实例,我们必须给函数传递一个实例。实例方法可以操作类属性、对象属性

在python中要定义严格的类方法、静态方法,需要使用内置的装饰器函数classmethod()、staticmethod()来装饰。
实例可以调用实例方法,类方法,静态方法。类可以调用实例方法,类方法,静态方法
类方法和静态方法只能操作类属性。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class test_2:
    #实例方法
    def m1(self, arg1):
        print(arg1)
  
    #类方法,因为@classmethod已经将m2包装成了类方法,所以m2的第一个self参数将总是代表类名。
    @classmethod
    def m2(self, arg1):
        print(arg1)
  
    #静态方法
    @staticmethod
    def m3(arg1, arg2):
        print(arg1, arg2)
  
c = test_2()
  
# 用实例名来访问。调用实例方法
c.m1("hello m1"# hello
# 用实例名来访问。调用类方法。
c.m2("hello m2"# hello
# 用实例名来访问。调用静态方法。
c.m3("hello", "m3"# hello world
  
# 用类来访问。调用实例方法。
test_2().m1("你好 m1") #你好 m1 不能用类名直接访问,要使用类名加括号
# 用类名来访问。调用类方法。
test_2().m2("你好 m2") #你好 m2  可以用类名直接访问,也可以使用类名加括号
# 用类名来访问。调用静态方法。
test_2().m3("你好","m3") #你好 m3  可以用类名直接访问,也可以使用类名加括号

 

四、类的方法的调用

1.类的内部调用:self.<方法名>(参数列表)。
2.在类的外部调用:<实例名>.<方法名>(参数列表)。
注意:以上两种调用方法中,提供的参数列表中都不用包括self。

第一种:class内部函数与函数之间的调用(a调用b,只需在a中加上 self.b即可)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Student(object):
    count = 0
    books = []
    sex = 'man'
  
    def __init__(self, name, age):
        self.name = name
        self.age = age
     
    def chg(self):
        pp=self.sex #调用类属性
        print('函数chg')
        print(pp)
 
    def prt(self):
        self.chg() #调用类方法
 
tester=Student('xiaoming',24)
tester.prt() #函数chg  man

第二种:Class之间函数的调用关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<strong>#方法一:在Class B的函数中声明Class A的对象a,然后用对象a来调用Class A的函数a()</strong>
class A(): 
    def __init__(self,parent): 
        self.parent = parent 
   
    def a(self): 
        print('Class A')
 
class  B(): 
    def fuction(self): 
        a = A(None
        a.a() 
 
if __name__ == '__main__'
    b = B() 
    b.fuction()   #Class A
 
 
#方法二:在Class B的__init__()中将Class A和Class B产生关联。
class A(): 
    def __init__(self,parent): 
        self.parent = parent 
   
    def a(self): 
        print("Class A" )
   
class B(object): 
    def __init__(self,object): 
        self.object = object 
        self.object.a() 
   
    def b(self): 
        print("Class B" )
   
if __name__ == '__main__'
    a = A(None
    b = B(a) 
    b.b()  #Class A Class B
 
#方法三: 直接在Class B中声明Class A的对象,该对象是Class B的self.A_object。
class A(): 
    def __init__(self,parent): 
        self.parent = parent 
 
    def a(self): 
        print("Class A" )
   
class B(object): 
    def __init__(self): 
        self.A_object = A(None
        self.A_object.a() 
   
    def b(self): 
        print("Class B")
   
if __name__ == '__main__'
    b = B() 
    b.b()  #Class A  Class B

 

五、面向对象三大特性(封装,继承,多态)

1)封装:将代码写到类里面即是封装,并且封装还可以给属性或者方法设置权限。在上述代码中已经使用了封装的特性。
2)继承:指的是类当中的从属关系,子类自动拥有父类所有的属性和方法。所有的类都默认继承Object类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#单继承:只继承一个父类。
class Father():
    def __init__(self):
        self.name= "可乐家族"
  
    def get_name(self):
        print(self.name)
  
class Son(Father):
    pass
  
son= Son()
son.get_name()# 可乐家族
  
 
#多继承:子类同时继承多个父类。如果继承的父类当中拥有相同的属性或者方法,那么优先继承第一个父类的属性和方法。
class Father():
  
    def __init__(self):
        self.name= "可乐家族"
  
    def get_name(self):
        print(self.name)
  
class Mother():
  
    def __init__(self):
        self.name= "雪碧家族"
  
    def get_name(self):
        print(self.name)
  
class Son(Mother, Father):
    pass
  
son= Son()
son.get_name()# 雪碧家族
 
 
#重写父类的方法,继承中支持子类对父类的方法进行重写。子类重写父类方法,但是还需要调用父类的同名方法时,可使用super()去调用父类的方法。
class Father:
    def __init__(self):
        self.name = "可乐家族"
 
    def get_name(self):
        print(self.name)
 
class Mother:
    def __init__(self):
        self.name = "雪碧家族"
 
    def get_name(self):
        print(self.name)
 
    def add_water(self):
        print("生命之源")
 
 
class Son(Mother, Father):
    def get_name(self):
        print("碳酸家族")
 
    def get_old(self):
        super().get_name()  #必须在子类的定义中才能调用
 
son = Son()
 
son.get_name()  # 碳酸家族      重写父类的方法
son.add_water()  # 生命之源     未重写父类方法,可直接调用
son.get_old()  # 雪碧家族
3)多态:多个子类分别重写了父类的某方法,调用这些子类的该方法,有不同的结果。多态可以使得代码变得更加灵活,更适应的业务场景多。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Person:
    def get_sex(self):
        print("人")
class Man(Person):
    def get_sex(self):
        print("男人")
class Women(Person):
    def get_sex(self):
        print("女人")
man = Man()
women = Women()<br>
man.get_sex() #男人
women.get_sex() #女人
 
 
posted @   liangww  阅读(195)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示