python 面向对象

Posted 折翼の翅膀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 面向对象相关的知识,希望对你有一定的参考价值。

面向对象

1.1 类的构造方法

  • __init__构造方法
    • 调用时间:在对象被实例化时被程序自动调用
    • 作用:用于对象创建时初始化
    • 书写格式:init前后分别是2个下划线
    • 程序不显示定义init方法,则程序默认调用一个无参数的init方法
    • 对象创建过程(无参)
  • 设置对象属性(有参)

 

  • 创建对象过程(有参)

 

1.2 类的方法权限

  • 修改对象属性的方法
    • 方法1:对象变量名.属性 = 新值

问题:

可能修改的属性值不合法

在类的外部可以随意修改类的内部属性

  • 方法2:对象变量名.内部修改属性方法
  • 私有属性
    • 定义:__私有变量名
    • 只能在类内部使用,类外部不能访问,否则报错
  • 私有方法
    • 只能在类内部调用,在类的外部无法调用
    • 定义私有方法在方法名前添加2个下划线:__私有方法()
    • 类内部调用私有方法要使用self.私有方法的方式调用
#私有方法的定义&&使用
class Comrade:
    # 私有方法
    def __send_message(self):
        print("消息已经向上级汇报")
    def answer_secret(self, secret):
        if secret == "芝麻开门":
            print("接头成功!")
            self.__send_message() # 调用私有方法
        else:
            print("接头失败!")
comrade = Comrade()
comrade.answer_secret("芝麻开门"

1.3 继承

class Rectange:
    def __init__(self,length,width):
        self.length=length
        self.width=width
    def area(self):
        return self.length+self.width
    def permeter(self):
        return (self.length+self.width)*2
    @classmethod
    def fearure(cls):
        print(\'两边的长宽都相等\')
    @staticmethod
    def static():
        print(\'静态方法的使用\')
res = Rectange(5,4)
print(res.__dict__)
# print(Rectange(5,4).area()) #调用实例方法的面积
# print(Rectange(5,4).permeter()) #调用实例方法的周长
# Rectange.area(3,4) #类不能调用实例方法,会报错
Rectange(5,4).fearure() #实例方法调用类方法
Rectange.fearure() #类调用类方法
Rectange(5,4).static() #静态方法调用类
Rectange.static() #静态方法调用实例
#type类型查看某个方法是否是函数还是方法。
# print(type(res.fearure)) #fearure是类方法
# print(type(res.static))  #static是函数,静态方法
# #inspect模块,可以判断某个对象是否是某种类型。
# import inspect
# print(inspect.ismethod(res.fearure)) #True,判断是否是方法。
# print(inspect.ismethod(res.static)) #False
# print(inspect.isfunction(res.static)) #True,判断是否是函数。

#继承
#1.完成继承
class Square(Rectange):
    pass
squ =Square(6,6)
print(squ.permeter())
print(squ.area())

#2.部分继承
class Square_some(Rectange):
    def __init__(self,side):
        self.length =side
        self.width=side
squ1=Square_some(6)
print(squ1.area())
print(squ1.permeter())

#3.全部重写,相当于没有继承。
class requre(Rectange):
    def __init__(self,side):
        self.length=side
    def area(self):
        return self.length*4
    def permeter(self):
        return self.length*2
squ2=requre(7)
print(squ2.area())
print(squ2.permeter())
  • 在程序中,继承描述的是类中类型与子类型之间的所属关系,例如猫和狗都属于动物
  • 单继承如果在子类中没有定义init构造方法,则自动调用父类的init构造方法;如果子类中已定义init构造方法,则不会调用父类的构造方法
    • 子类继承一个父类,在定义子类时,小括号()中写父类的类名
    • 父类的非私有属性、方法,会被子类继承
    • 子类中方法的查找方式:先查找子类中对应的方法,如果找不到,再到父类中查找
    • 子类可以继承父类的非私有属性和方法,也可继承父类的父类的非私有属性和方法,以此类推
    • 在子类中调用父类的方法:ClassName.methodname(self)
  • 重写父类方法

    • 子类对父类允许访问的方法的实现过程进行重新编写
    • 在子类中定义与父类同名的方法
    • 优点:子类可以根据需要,定义合适的方法实现逻辑
  • 多继承

    • Object类是所有类的基类,在定义类的时候不需要显示的在括号中表明继承自object类
    • 多继承:一个子类可以继承多个父类
    • 多继承定义方式:在类名后的括号中添加需要继承的多个类名
    • 多继承中,如果多个类中有同名的方法,子类调用查找方法的顺序是按照小括号内继承父类从左到右的顺序查找,第一个匹配的方法名的父类方法将会被调用
  • 多态

    • 一个抽象类有多个子类,不同的类表现出多种形态

1.4 类属性、类方法、静态方法、类的特殊成员方法

  • 实例属性(对象属性)
    • 在构造方法之内里定义的属性
    • 属于具体的实例对象,不同实例对象之间的实例属性互不影响
  • 类属性
    • 在构造方法之外但在类里定义的属性
    • 属于类对象(类名),多个实例对象之间共享同一个类属性
    • 获取类属性方法:类名.类属性
    • 通过实例对象不能够修改类属性,如果修改的属性在实例中不存在,则动态添加实例属性

#类对象
class Person:
    sum_num = 0

    def __init__(self, new_name):
        self.name = new_name
        Person.sum_num += 1

p1 = Person("zhangsan")
print(p1.sum_num, Person.sum_num)
p2 = Person("lisi")
print(p1.sum_num, p2.sum_num, Person.sum_num)

#结果显示如下:
1 1
2 2 2 
  • 类方法
    • 所属于类对象,使用@classmethod修饰的方法,主要用于操作类属性,不能操作实例属性
    • 定义类方法的第一个参数通常以”cls”参数作为类对象被传入
    • 调用方式:类名.类方法  或者  实例对象.类方法(不推荐)
# 类方法
@classmethod
def add_sum_num(cls):
    cls.sum_num += 1
    print(cls.sum_num) 
  • 静态方法
    • 使用@staticmethod修饰的方法,不需要传递任何默认参数。不能操作实例属性

    • 调用方式:类名.静态方法  或者  实例对象.静态方法

@staticmethod
def static_test():
    print("-------静态方法-------")
    Person.sum_num += 1
    print(Person.sum_num) 
  • 类的特殊成员方法

    __doc__:表示类的描述信息

    __module__:表示当前操作的对象在哪个模块

    __class__:表示当前操作的对象的类时什么

    __init__:构造方法,通过类创建对象时,自动触发执行 

    __del__:析构方法,当对象在内存中被释放时,自动触发执行

    __call__:对象后面加括号,触发执行

    __dict__:查看类或对象中的所有成员

    __str__:如果一个类中定义了__str__方法,那么在打印对象时,默认输出该方法的返回值

    __new__\\__metaclass__:__metaclass__表示该类由谁来实例化创建

class Dog(object):
    """这个类是描述狗这个对象的"""
    def func(self):
        pass
print(Dog.__doc__)

from aa import C
obj =C()
print(obj.__module__) #输出aa,即:输出模块
print(obj.__class__) #输出aa.C,即:输出类

class Foo:
    def __init__(self):
        #构造方法,通过类创建自动触发执行
        print("__init__")
    def __call__(self,*args,**kwargs):
        #对象后面加括号,自动触发执行
        print("__call__")

obj1 = Foo() #对象=类名(),执行__init__
obj1()  #对象()或者类()(),执行__call__

class Province:
    country =\'china\'
    def __init__(self,name,count):
        self.name = name
        self.count = count

    def func(self):
        print("func")
print(Province.__dict__) #获取类的成员,不包括实例属性
obj2=Province("chongqing",1000)
print(obj2.__dict__)#获取对象obj2的成员,不包括类属性

class Foo:
    def __str__(self):
        return \'wendy\'
obj3 = Foo()
print(obj3)

#结果显示如下
这个类是描述狗这个对象的
aa
<class \'aa.C\'>
__init__
__call__
{\'__module__\': \'__main__\', \'country\': \'china\', \'__init__\': <function Province.__init__ at 0x000001AC81A9C5E8>, \'func\': <function Province.func at 0x000001AC81A9C8B8>, \'__dict__\': <attribute \'__dict__\' of \'Province\' objects>, \'__weakref__\': <attribute \'__weakref__\' of \'Province\' objects>, \'__doc__\': None}
{\'name\': \'chongqing\', \'count\': 1000}
wendy
类的特殊成员方法 

1.5 单例类

  • __new__(cls)

    • 超类object类内置的方法,用户创建对象,返回创建对象的引用

    • 必须提供cls参数,代表类对象

    • 必须要有返回值,返回创建对象的引用

class DataBaseObj(object):
    def __init__(self, new_name): # 对象初始化
        print("----init构造方法----")
        self.name = new_name
        print(self.name)

    def __new__(cls, name): # 创建对象
        print("cls_id:", id(cls))
        return object.__new__() # 必须有返回值,返回的是创建的对象的引用 
  • 单例类

    • 在整个程序系统中确保某一类只有一个实例对象

# 单例类
class SingleInstance:
    __instance = None

    def __init__(self):
        print("-----init-----")
    def __new__(cls):
        if cls.__instance is None:
            cls.__instance = object.__new__(cls)
        return cls.__instance

s1 = SingleInstance()
print(id(s1))
s2 = SingleInstance()
print(id(s2))

#显示结果

-----init-----
2664579822280
-----init-----
2664579822280

1.6 异常处理

  • 捕获异常
try:

逻辑代码块

except ExceptionType as err:

异常处理方法
  • 捕获多个异常
try:

逻辑代码块

except (ExceptionType1, ExceptionType2, …) as err:

异常处理方法
  • 捕获所有可能发生的异常
try:

逻辑代码块

except (ExceptionType1, ExceptionType2, …) as err1:

异常处理方法

except Exception as err2:

异常处理方法
  • finally
try:

逻辑代码块

except (ExceptionType1, ExceptionType2, …) as err1:

异常处理方法

except Exception as err2:

异常处理方法

finally:

无论是否有异常产生,都会执行这里的代码块!
  • Python标准异常类型

https://www.runoob.com/python/python-exceptions.html

  • 函数嵌套异常传递

1.7 包和模块

一个项目可以包含多个包,一个包可以包含多个模块,一个模块就是一个以.py结尾的文件,一个模块内可以定义变量、函数、类等。

  • 模块的名字:.py结尾的文件
  • 包下可以包含子包
  • 不同包下可以有相同的模块名称,使用“包名.模块名”的方式区分
  • 引入模块的方式
引入单个模块:import module_name

引入多个模块:import module_name1, module_name2, …

引入模块中的指定函数:

from module_name import func1, func2, …
  • 包中必须包含一个默认的__init__文件

用于标识一个包,而不是普通的文件夹

会在包或者该包的模块被引用时自动调用

常用于设置包和模块的一些初始化操作, 比如批量导入时限制部分模块可被导入

正则表达式

2.1 re模块的使用

  • match(正则表达式,待匹配字符串)

用于正则匹配检查,如果待匹配字符串能够匹配正则表达式,则match方法返回匹配对象,否则返回none

采用从左往右逐项比较匹配

  • group()方法

用来返回字符串的匹配部分

import re

rs = re.match("chinahadoop", "chinahadoop.com")
print(rs)
if rs is not None:
    print(rs.group())

2.2 字符匹配、数量表示、边界表示

2.2.1 单字符匹配

字符

描述

.

匹配除“\\n”之外的任意单个字符                         

rs = re.match(".","a")
print(rs.group())     #显示结果为:a
rs = re.match(".","1")
print(rs.group())   #显示结果为:1
rs = re.match("...","abc")
print(rs.group())   #显示结果为:abc
rs = re.match(".","\\n")
print(rs)       #显示结果为:None

 

\\d

匹配0-9之间的一个数字,等价于[0-9]

\\D

匹配一个非数字字符,等价于[^0-9]

\\s

匹配任意空白字符,如空格、制表符“\\t”、换行“\\n”等

rs = re.match("\\s","\\t")
print(rs)
rs = re.match("\\s","\\n")
print(rs)
rs = re.match("\\s"," ")
print(rs)

 

\\S

匹配任意非空白字符

rs = re.match("\\S","\\t")
print(rs)
rs = re.match("\\S","abc")
print(rs)

 

\\w

匹配任意单词字符(包含下划线),如a-z,A-Z,0-9,_

rs = re.match("\\w","a")
print(rs)
rs = re.match("\\w","A")
print(rs)
rs = re.match("\\w","1")
print(rs)
rs = re.match("\\w","_")
print(rs)
rs = re.match("\\w","中")
print(rs)
rs = re.match("\\w","*") #非单词字符
print(rs)

 

\\W

匹配任意非单词字符,等价于[^a-zA-Z0-9]

[]

匹配[ ]中列举的字符

rs = re.match("[Hh]","hello")
print(rs)
rs = re.match("[Hh]","Hello")
print(rs)
rs = re.match("[0123456789]","32")
print(rs)
#等价
rs = re.match("[0-9]","3")
print(rs)

 

^

取反

2.2.2 数量表示

字符

描述

*

一个字符可以出现任意次,也可以一次都不出现

rs = re.match("1\\d*","1234567")
print(rs.group())
rs = re.match("1\\d*","1234567abc")
print(rs.group())

 

+

一个字符至少出现一次

rs = re.match("\\d+","abc")
print(rs)
rs = re.match("\\d+","1abc")
print(rs)
rs = re.match("\\d+","123345abc")
print(rs)

 

?

一个字符至多出现一次

rs = re.match("\\d?","abc")
print(rs)
rs = re.match("\\d?","123abc")
print(rs)

 

{m}

一个字符出现m次

#{m}固定次数
rs = re.match("\\d{3}","123abc")
print(rs)

 

{m,}

一个字符至少出现m次

#{m,}
rs = re.match("\\d{1,}","123467abc")#等价于+至少一次
print(rs)

 

{m,n}

一个字符出现m到n次

rs = re.match("\\d{0,1}","abc") #等价于?至多一次
print(rs)

 


#匹配11位的手机号

#11位,第一位1,第二位3,5,7,8 第3位到第11为0到9的数字
\'\'\'
rs = re.match("1[3578]\\d{9}","13623198765")
print(rs)

#转义字符处理

str3 = r"hello\\\\world"#原生字符串
print(str3)
rs = re.match(r"\\w{5}\\\\\\\\\\w{5}",str3)
print(rs)

2.2.3 字符串与单词边界

字符

描述

^

用于匹配一个字符串的开头

$

用于匹配一个字符串的结尾

#邮箱匹配
rs = re.match("\\w{3,10}@163\\.com$","hello_124@163.com")
print(rs)
rs = re.match("\\w{3,10}@163\\.com$","hello_124@163mcom")
print(rs)

 

\\b

用于匹配单词的边界

rs = re.match(r".*\\bpython\\b","hi python hello")
print(rs)

 

\\B

用于匹配非单词边界

rs = re.match(r".*\\Bth\\B","hi python hello")

 

2.2.4 匹配分组

字符

描述

|

表示或,匹配 | 链接的任何一个表达式

()

将括号中字符作为一个分组

import re
rs = re.match("\\w{3,10}@(163|qq|outlook)\\.com$","hello@163.com")
print(rs)
rs = re.match("\\w{3,10}@(163|qq|outlook)\\.com$","1234567@qq.com")
print(rs)

 

\\NUM

配合分组()使用,引用分组NUM(NUM表示分组的编号)对应的匹配规则

#\\num
html_str = "<head><title>python</title></head>"
rs = re.match(r"<.+><.+>.+</.+></.+>",html_str)
print(rs)
rs = re.match(r"<(.+)><(.+)>.+</\\2></\\1>",html_str)
print(rs)

 

(?P<name>)

给分组起别名

rs = re.match(r"<(?P<g1>.+)><(?P<g2>.+)>.+</(?P=g2)></(?P=g1)>",html_str)
print(rs)

 

(?P=name)

应用指定别名的分组匹配到的字符串

2.3 高级用法

  • search:从左到右在字符串的任意位置搜索第一次出现匹配给定正则表达式的字符

#search
rs = re.search("car","haha car carbal abcar carbal")
print(rs)

  • findall:在字符串中查找所有匹配成功的组,返回匹配成功的结果列表

#findall
rs = re.findall("car","haha car carbal abcar carbal")
print(rs)
mail_str = "zhangsan:helloworld@163.com,li:123456@qq.cn"
list = re.findall(r"(\\w{3,20}@(163|qq)\\.(com|cn))",mail_str)
print(list)

  • finditer:在字符串中查找所有正则表达式匹配成功的字符串,返回iterator迭代器

#finditer
itor = re.finditer(r"\\w{3,20}@(163|qq)\\.(com|cn)",mail_str)
for it in itor:
   print(it.group())

  • sub:将匹配到的数据使用新的数据替换

#sub
str = "java python c cpp java"
rs = re.sub(r"java","python",str)
print(rs)

  • split:根据指定的分隔符切割字符串,返回切割之后的列表

#split
str_test = "apple=5,banana=3,orange=2"
price_list = str_test.split(",")
for price in price_list:
   print(price)

2.4 贪婪与非贪婪模式

  • 贪婪模式:正则表达式引擎默认是贪婪模式,尽可能多的匹配字符,匹配数量为上限

#贪婪模式
rs = re.findall(r"hello\\d*","hello12345")
print(rs)
rs = re.findall(r"hello\\d+","hello12345")
print(rs)
rs = re.findall(r"hello\\d?","hello12345")
print(rs)
rs = re.findall(r"hello\\d{2,}","hello12345")
print(rs)
rs = re.findall(r"hello\\d{1,3}","hello12345")
print(rs)

  • 非贪婪模式:尽可能少的匹配字符;在表示数量的“*”,“?”,“+”,“{m,n}”符号后面加上?,使贪婪变成非贪婪。匹配数量为下限

#非贪婪模式
rs = re.findall(r"hello\\d*?","hello12345")
print(rs)
rs = re.findall(r"hello\\d+?","hello12345")
print(rs)
rs = re.findall(r"hello\\d??","hello12345")
print(rs)
rs = re.findall(r"hello\\d{2,}?","hello12345")
print(rs)
rs = re.findall(r"hello\\d{1,3}?","hello12345")
print(rs)

 

以上是关于python 面向对象的主要内容,如果未能解决你的问题,请参考以下文章

python之路之前没搞明白4面向对象(封装)

Python面向对象学习之八,装饰器

python:第二部分:面向对象:面向对象object orinted

面向面试编程代码片段之GC

Python 面向对象

面向对象编程其实很简单——Python 面向对象(初级篇)