python面向对象编程的三大特性_Python面向对象总结及类与正则表达式详解

Python3 面向对象

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

一丶面向对象技术简介

•类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

•方法:类中定义的函数。

•类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。

•数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。

•方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。

•局部变量:定义在方法中的变量,只作用于当前实例的类。

•实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。

•继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。

•实例化:创建一个类的实例,类的具体对象。

•对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。

Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。

对象可以包含任意数量和类型的数据。

1.类中带下划线开头的变量特点

类中的方法,其实就是类中的函数,可以分为:实例方法,类方法,静态方法。方法和字段一样,也是属于类的属性,所以也具有运行中修改的特效, 但一般不推荐这样做。

我在类的基本语法中,介绍了构造器方法:__init__ 、__new__;解构器方法:__del__;

注意,这里虽然是以两个下划线(__)开头,但同时以两个下划线(__)结尾,这里表明其是一个‘魔法方法',关于类中的魔法方法,将起一篇进行说明。

但是,如果单纯只以两个下划线开始,则依然是私有化的意思,看代码示例:

class Test(object):

def __scolia__(self): # 一个类似魔术方法,并不是私有化

return 'scolia'

def __good(self): # 私有方法

return 'good'

a = Test()

print a.__scolia__() # 魔法方法可以在直接访问

print a.__good() # 私有方法不能直接访问

同样的,和字段私有化一样,我们也可能同特殊手段进行强制访问:

print a._Test__good() # 强制访问

当然,私有方法也可以在类的内部访问,和私有字段一样。

所以说,属性的私有化都是对访问入口进行混淆,同样的,也不建议强制访问私有属性。

也许这里的‘魔法方法'看起来并不‘魔法',详情将以后解释。

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

实例方法:

在 __init__ 构造器中,提起过其是一个实例方法,实例方法的特点就是:

1.方法的第一个参数必须是 self,当然这是约定俗成的写法,你可以将 self 换成 abc 之类的,但是为了别的程序员能看得懂,还是统一用 self 吧。这里的 self 代表实例本身,也就是说如果我实例化时使用的是: a = Test() ,那么 self 就代表 a 这个实例,我们可以在很多构造器中看到类似self.scolia = 'good'的写法,其实这个写法和在类外面 a.scolia = 'good' 效果一样,是为了添加属性,只不过 __init__ 方法是实例化时自动调用的函数,所以适合进行初始属性的创建。

2.实例方法在调用的时候,self 是自动传递的,所以不需要我们再处理。

3.实例方法一般要有实例才能调用,当然也有特殊的调用方法。

代码示例:

class Test(object):

def __init__(self, a, b): # 构造器在实例创建时进行属性的初始化

self.a = int(a)

self.b = int(b)

def abc(self, c): # 实例方法

print self.a + self.b + int(c) # 因为self是自动传递的,所以我们可以在实例方法中调用实例的属性

a = Test(123, 321) # 我们只要为 a 和 b 传参就行了

a.abc(666) # 同样的,只要为 c 传参

这里,将引入一个绑定 (binding) 的概念,其主要和方法的调用有关。

首先,我们知道方法是类的属性,而不是实例的属性,在上篇博文类的属性和实例的属性中我们也讨论过这个问题。

其次,方法只有在其所属的类拥有实例时,才能被调用。当一个类存在实例后,方法才被认为是绑定到这个实例。没有实例的时候,方法是未绑定的。

最后,任何一个方法定义的第一个参数都是变量 self ,它表示调用此方法的实例对象。

很明显这里的绑定针对的是实例方法。因为如果没有实例的话,self 就无法传递,这将导致参数的不足,当然就无法调用了。

但是,我们可以自己传递 self 来调用未绑定的方法。调用未绑定的方法通常是在我们继承了一个父类后, 我们覆盖了父类中的某个方法,但是为了实现代码重用,我们又想在子类中调用父类的方法。单纯的复制父类中的代码明显不是一个好选择, 除了浪费系统资源之外,还有可能在复制的时候出错,而且以后修改父类的代码之后,还要修改相应子类中的代码,实在太低效,这个时候就是调用未绑定方法的场景。

代码示例:

class abc(object):

def __init__(self, a):

self.a = -int(a)

class Test(abc):

def __init__(self, a, b):

abc.__init__(self, a) # 调用父类的构造器,并手动传递 self

self.b = b

def fangfa(self):

print self.a + self.b # 属性 a 由父类的构造器创建,b 由子类构造器创建

a = Test(123, 321) # 我们只创建了子类的实例,而没有创建父类的实例

a.fangfa()

本来我们没有创建父类的示例,是无法调用父类的实例方法的,但是我们手动传递了实例方法需要的 self 参数,就可以实现调用了。

这里的顺序是,我们创建了 Test 的实例,其 self 是自动传递的,故 Test 的构造方法 __init__(self, a, b) 中 self 就代表实例 a,而我们又调用了父类的 abc.__init__(self, a) 这里的 self 就是子类的实例 a ,参数 a 就是我们传的 123,而父类中 self.a = -int(a) ;最后我们可在子类的方法中调用 self.a 这个属性。

2.Python面向对象的三大特性

一、继承

面向对象中的继承就是继承的类直接拥有被继承类的属性而不需要在自己的类体中重新再写一遍,其中被继承的类叫做父类、基类,继承的类叫做派生类、子类。在python3中如果不指定继承哪个类,默认就会继承Object类,而继承了Object类的类就叫做新式类,而在python2中如果不指定继承哪个类也不会默认去继承Object类,而没有继承Object类的类就叫做经典类。经典类和新式类的不同就在于对方法的搜索顺序不同,经典类是深度优先即先找自己类内,如果没有就找左边第一个父类,没找到继续从这个父类的父类中找依次类推直到找到最上一级的父类也没找到再找左边第二个父类,然后再重复之前的过程,直到所有父类找一遍没找到就报错;而新式类是广度优先,当下一个类可以通过其他类找到时就先不去找它,而是找继承关系中与它的子类同级的其他类,依次类推直到最后找到object类没有找到指定方法就报错。新式类搜索顺序图示如下,还可以通过类名.mro()查看新式类继承中的属性搜索顺序

201904180925312.png

二、单继承与多继承

在其他语言中只支持单继承即class 类名(父类名),而python支持多继承,用逗号将多个父类隔开即class 类名(父类名1,父类名2,。。。。)

三、继承与抽象

抽象就是把一类事物的共有特性提取出来,继承则是把父类的属性拿过来并且还拥有自己的属性。抽象是包含的范围越来越大,共性越来越少,继承则是包含的返回越来越小,共性越来越多。我们定义父类的过程就是抽象,定义子类的过程就是继承。

四、父类方法重写

我们把子类有而父类没有的方法叫做子类的派生方法,而父类有子类也有的方法叫做对父类方法的重写,因为按照类方法的搜索顺序一个方法如果在子类中有就不会再从父类中找了,结果就是父类中的方法无法调用了,如果既想执行父类中的方法同时在子类中又能定义新功能,就需要先把父类中的这个方法单独继承过来,在python中只能使用父类名.方法名(self,父类的其他参数)的方式,在python3中可以使用super函数来实现,比如super().父类方法名(除self外的其他参数),其实在super函数中还需要传入子类名和子类对象(在类中用self),但是我们使用时不需要特意去传,除非在类外单独调用父类的方法。注意在继承父类方法时父类的参数除了需要在父类的方法中传递还需要在子类重写的方法中传递

class Animal:

def __init__(self,name,life_value,aggr):

self.name=name

self.life_value=life_value

self.aggr=aggr

def eat(self):

self.life_value+=10

class Person(Animal):

def __init__(self,money,name,life_value,aggr):

super().__init__(name,life_value,aggr)

self.money=money

def attack(self,obj):

obj.life_value-=self.aggr

五、接口类

接口类是用于规范子类的方法名定义用的,继承接口类的子类可以不存在任何逻辑上的关系但是都需要实现某些共同的方法,为了让这些子类的方法名能够统一以便之后调用这些方法时不需要关注具体的对象就用接口类规范了这些方法的名字,子类一旦继承了接口类就必须实现接口类中定义的方法,否则在子类实例化的时候就会报错,而接口类本身则不需要实现去实现这些方法。

from abc import ABCMeta,abstractmethod

class Payment(metaclass=ABCMeta):

@abstractmethod

def pay(self,money):pass

class Wechatpay(Payment):

def pay(self,money): #子类中必须定义接口类中有的方法,否则实例化会报错

pass

w1=Wechatpay()

六、抽象类

抽象类的作用和接口类一样,只是继承它的子类一般存在一些逻辑上的关系,且抽象类中的方法可以去实现,子类在重写时用super函数调用抽象类的方法即可,同时在用抽象类时使用单继承,使用接口类时使用多继承

七、多态

多态就是不同的对象可以调用相同的方法然后得到不同的结果,有点类似接口类的感觉,在python中处处体现着多态,比如不管你是列表还是字符串还是数字都可以使用+和*。

八、封装

封装就是把类中的属性和方法定义为私有的,方法就是在属性名或方法名前加双下划线,而一旦这样定义了属性或方法名后,python会自动将其转换为_类名__属性名(方法名)的格式,在类的内部调用还是用双下划线加属性名或方法名,在类的外部调用就要用_类名__属性名(方法名)。父类的私有属性和方法,子类无法对其进行修改。

九、类的装饰器

property属性装饰器:将类内的方法的调用方式和属性一样,这个装饰器还有和其配套的setter、deleter。

class Demo:

@property

def p(self):

print('property func')

@p.setter

def p(self,num):

print('property_setter')

@p.deleter

def p(self):

print('在删除')

d=Demo()

d.p

d.p=10

del d.p

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

property func

property_setter

在删除

staticmethod静态方法装饰器:将类内的方法变成普通的函数,或者把类外的函数放到类内当作方法调用

class A:

@staticmethod

def sum(): #这个方法跟普通函数没有区别

print('staticmethod')

A.sum() #用类名调用

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

staticmethod

classmethod类方法装饰器:该方法用于操作类属性,无法操作对象属性

class A:

role='male'

@classmethod

def sum(cls): #用于操作类属性

print(cls.role)

A.sum() #用类名调用

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

male

十、isinstance和type的区别以及issubclass

isinstance和type都可以用于判断对象和指定类间的关系,但是isinstance的判断没有type准确,它无法正确判断子类的对象和其父类的关系

class A:

pass

class B(A):

pass

b=B()

print(isinstance(b,B))

print(isinstance(b,A))

print(type(b) is B)

print(type(b) is A)

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

True

True

True

False

issubclass用于判断给定的两个类,前者是否是后者的子类

十一、反射

hasattr(对象或类名,‘属性或方法名') 判断指定的对象或类中是否存在指定的属性或方法,有返回True

getattr(对象或类名,'属性或方法名') 获取对象或类的指定属性值或方法的内存地址

setattr(对象或类名,‘新属性名',新属性值) 给对象或类添加新的属性或方法

delattr(对象或类名,‘新属性名') 删除之前添加的属性

十二、类的内置方法

__doc__ :输出类的描述信息

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

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

__dict__ :查看类或对象中的所有成员 类调用打印类的所有属性,不包括实例属性。实例调用打印所有实例属性

__str__ 格式化输出%s输出该方法的值

__repr__ 格式化输出%r输出该方法的值,并且%s在没有__str__方法时也是输出该方法的值

__del__ del 执行该方法

__getitem__ 用对象加[]方式取值

class A:

def __init__(self):

self.names=['egon','alex','eva'] #可以是其他序列

def __getitem__(self, item):

print(self.names[item])

a=A()

a[1]

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

alex

__setitem__ 添加值

__delitem__ 删除值

__new__ 用于创建没有属性的对象,调用object的__new__即可不需要自己实现。可以利用该方法实现单例模式

__call__ 对象加括号执行该方法

__len__ len()执行该方法

__eq__ ==运算输出该方法的值

__hash__ hash执行该方法

二丶代码实现(三维向量类)

class Vecter3:

def __init__(self, x=0, y=0, z=0):

self.X = x

self.Y = y

self.Z = z

def __add__(self, n):

r = Vecter3()

r.X = self.X + n.X

r.Y = self.Y + n.Y

r.Z = self.Z + n.Z

return r

def __sub__(self, n):

r = Vecter3()

r.X = self.X - n.X

r.Y = self.Y - n.Y

r.Z = self.Z - n.Z

return r

def __mul__(self, n):

r = Vecter3()

r.X = self.X * n

r.Y = self.Y * n

r.Z = self.Z * n

return r

def __truediv__(self, n):

r = Vecter3()

r.X = self.X / n

r.Y = self.Y / n

r.Z = self.Z / n

return r

def __floordiv__(self, n):

r = Vecter3()

r.X = self.X // n

r.Y = self.Y // n

r.Z = self.Z // n

return r

def show(self):

print((self.X,self.Y,self.Z))

v1 = Vecter3(1,2,3)

v2 = Vecter3(4,5,6)

v3 = v1+v2

v3.show()

v4 = v1-v2

v4.show()

v5 = v1*3

v5.show()

v6 = v1/2

v6.show()

此类可实现三维向量的加减乘除

运行后为

201904180925313.png

三丶代码实现(程序类)

这个程序运用类与正则表达式匹配来写,可以删除重复的英文并输出,这里输入 This is my name

import re

class Good:

def __init__(self,n):

self.n = n

def love(self):

s1 = re.split(r' ',self.n)

s2 = sorted(set(s1),key=s1.index)

print(s2)

b = Good('This is is my name')#此处可自行输入字符串

b.love()

接下来我们看运行结果

201904180925314.png

总结

以上所述是小编给大家介绍的Python面向对象总结及类与正则表达式详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,我可以回答你关于Python正则表达式的问题。 Python正则表达式是一种用来匹配和处理字符串的工具。它可以在字符串中搜索和匹配特定的模式,以实现更高效和精确的数据处理。Python的re模块提供了完整的正则表达式支持,并且非常强大和灵活。 使用Python正则表达式,你可以实现各种字符串操作,比如搜索、替换、分割、提取等等。它的语法相对简单,但是功能非常强大,可以满足大部分的字符串处理需求。 在使用Python正则表达式时,你需要掌握一些基本的语法规则,比如元字符、字符集、重复、分组等等。这些语法规则可以组合在一起,形成复杂的匹配模式,以实现更加精细的字符串处理。 总之,Python正则表达式是一种非常有用的工具,可以大大提高字符串处理的效率和精确度。如果你想深入了解它的用法和技巧,可以查看Python官方文档中关于re模块的详细说明。 ### 回答2: Python正则表达式是一种强大的文本匹配和处理工具,通过使用特定的模式来识别和操作文本中的字符串。正则表达式通常被用于从文本中提取特定的信息、验证输入的有效性、进行替换或搜索等操作。 Python正则表达式的语法使用元字符和特殊字符来定义搜索模式,其中元字符用于描述字符型或位置,特殊字符用于描述重复次数或匹配方式。常见的元字符包括"."(匹配任意字符)、"\d"(匹配数字字符)、"\w"(匹配字母、数字或下划线字符)、"\s"(匹配空白字符)等。特殊字符包括"*"(匹配前面的模式0次或多次)、"+"(匹配前面的模式1次或多次)、"?"(匹配前面的模式0次或1次),以及花括号{}(指定前面模式的重复次数)等。 使用Python正则表达式时,常见的操作包括匹配、搜索、替换和分割。匹配操作通过`re.match()`或`re.search()`函数实现,用于从字符串的起始位置或任意位置开始匹配;搜索操作通过`re.findall()`或`re.finditer()`函数实现,用于在整个字符串中搜索匹配的内容;替换操作通过`re.sub()`函数实现,用于替换匹配到的内容;分割操作通过`re.split()`函数实现,用于按指定的模式分割字符串。 Python正则表达式还支持分组、捕获、非捕获、反向引用等高级特性,可通过使用括号`()`进行分组,并使用`\number`的方式引用分组匹配到的内容。 总而言之,Python正则表达式提供了一套强大且灵活的工具来处理文本匹配和处理的需求。学习和熟练掌握正则表达式的使用,对于处理和分析文本数据将大有裨益。 ### 回答3: Python正则表达式是一种用来匹配字符串模式的工具。它使用一种特殊的语法来描述字符串的模式,然后通过与给定的字符串进行比较,判断是否匹配。 在Python中,我们使用re模块来使用正则表达式。首先,我们需要导入re模块,然后使用re模块提供的函数来进行匹配操作。 正则表达式中的一些基本概念包括: 1. 字符组:用方括号[]表示,表示匹配其中的任意一个字符。例如[abc]表示匹配字符a、b或c。 2. 量词:用来表示匹配多个字符的数量。例如*表示匹配0个或多个字符,+表示匹配1个或多个字符,?表示匹配0个或1个字符。 3. 元字符:具有特殊含义的字符,例如.表示匹配除换行符外的任意字符,\d表示匹配任意一个数字字符。 4. 转义字符:使用反斜杠\来转义元字符。例如\.表示匹配点字符。 5. 边界匹配:^表示匹配字符串的开头,$表示匹配字符串的结尾。 可以通过这些基本概念进行复杂模式的匹配。例如,使用re模块的match函数可以判断一个字符串是否以某个模式开头,使用search函数可以在字符串中搜索匹配某个模式的子串,使用findall函数可以找到所有匹配的子串。 除了基本概念外,Python正则表达式还提供了一些更高级的功能,例如分组、捕获和替换等。 总之,Python正则表达式是一种强大的工具,可以用于字符串的匹配和处理。掌握正则表达式的基本语法和常用函数,可以帮助我们更高效地处理字符串操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值