数据形式属性及访问调整详解,Python面向对象之2

  python是壹门面向对象的言语,所以oop编制程序是必须的。

python的类和类的单承接,python承袭

  python是1门面向对象的言语,所以oop编制程序是必须的。

  下边,笔者就来计算一下自个儿的学习心得和学得的学问。

  1. 声澳优(Ausnutria Hyproca)个类

 

class Student(object):

  pass

 

 

class   是注脚类的机要字,Student  是类名称。括号之中 object
是在持续的时候才用的,要是未有持续其余类,就能承袭object类。

pass区域是类的点子和属性

 

私家属性只怕措施:私有属性可能措施是以双下划线开头的(_
_XXX),这些天性就是不得不类自身内部访问,子类只怕类的外表是不能够访问的。

受保证属性大概措施:受保证的质量和方式是指只好通过类和子类进行访问,格式是以单下划线早先的(_XXXX)。

 

  1. 上面,大家来创设叁个完好无缺的类

 

class Student(object):
    name=""  # 这个是类的属性
    age=""  # 这个也是累的属性
    __score=""    # 这个是类的私有属性,不能直接在类的外部进行访问,只能通过类的内部方法进行访问。

    def __init__(self,name,age,score): # 这个是类的构造方法
        self.name=name
        self.age=age
        self.__score=score     # 这个是私有属性,子类是没有办法访问的,只能自己使用

    def print_info(self): #这个是类的方法
        print(self.name)
        print(self.age)
        print(self.__score)  # 这样就是使用的类的内部方法访问私有属性

  def __age_change(self):              # 这个方法是类的私有方法,在内的外部无法进行访问,调用方式就是在类的内部在创建一个公有的方法来调用私有方法执行

      print("my love ")

  def use_age_change(self):   # 这方法就是用来调用私有方法的公有方法
      self.__age_change()

ins_zrs=Student("zhangrongshun",18,100)   # 实例的创建
ins_zrs.print_info()  # 用实例来调用方法

 

那正是类的创建到实例化的完整步骤。

 

类的构造方法的功效:就是用来伊始化对象的性质的

 

上边正是累的几次三番了,python里面包车型大巴类支持单承接和多继承,不过php只援救单继承,学习过php的同窗应该都领悟啊。

#这个类将会继承上面的类-----单继承
class U_student(Student):
    grade=""  # 在子类中新增加一个属性
    def __init__(self,name,score,age,grade):
        Student.__init__(self,name,score,age)   # 这个是Student的
        self.grade=grade

    def print_information(self):
        print(self.name)
        print(self.grade)
        print(self.age)

    def _p_name(self):
        print("li hai ")

d=U_student("zhangrongshun",88,22,6)
d.print_information()

# 注意 在继承类的属性的时候私有属性是不能被继承的

 

python是1门面向对象的语言,所以oop编程是必须的。
下边,作者就来计算一下本身的学习心得和学得的知识…

面向对象进阶

python类:class创制、数据格局属性及访问调控详解,python访问调控

在Python中,能够通过class关键字定义本身的类,然后经过自定义的类对象类创建实例对象。

python中创制类

始建贰个Student的类,并且完毕了那么些类的起始化函数”__init__”:

class Student(object):
    count = 0
    books = []
    def __init__(self, name):
        self.name = name

数据形式属性及访问调整详解,Python面向对象之2。接下去就经过地点的Student类来看望Python中类的连带内容。

类协会和初叶化

”__init__”和”__new__”的联系和出入

上边先通过一段代码看看这多个措施的调用顺序:

class A(object):
  def __init__(self,*args, **kwargs):
    print "init %s" %self.__class__
  def __new__(cls,*args, **kwargs):
    print "new %s" %cls
    return object.__new__(cls, *args, **kwargs)

a = A() 

从代码的出口可以看到,当通过类实例化三个对象的时候,”__new__”方法首先被调用,然后是”__init__”方法。

澳门葡京备用网址 1

相似的话,”__init__”和”__new__”函数都会有上边包车型大巴款式:

def__init__(self,*args,**kwargs):
  # func_suite

def__new__(cls,*args,**kwargs):
  # func_suite
returnobj

对于”__new__”和”__init__”能够包罗为:

•“__new__”方法在Python中是当真的构造方法(创立并赶回实例),通过这些方法能够生出四个”cls”对应的实例对象,所以说”__new__”方法自然要有重回

•对于”__init__”方法,是3个开始化的方式,”self”代表由类产生出来的实例对象,”__init__”将对那几个目的开始展览对应的早先化操作

__new__特性

“__new__”是在风行类中新出现的章程,它有以下行为特征:

•“__new__” 方法是在类实例化对象时首先个调用的格局,将赶回实例对象

•“__new__”
方法始终皆以类的静态方法(即首先个参数为cls),固然未有被抬高静态方法装饰器

•第3个参数cls是近来正在实例化的类,要是要博取当前类的实例,应当在当下类中的
“__new__” 方波兰语句中调用当前类的父类的” __new__” 方法

对于地方的第一点,假如当前类是直接接轨自 object,那当前类的
“__new__” 方法再次来到的靶子应当为:

 

def __new__(cls, *args, **kwargs):
  # func_suite
return object.__new__(cls, *args, **kwargs) 

重写__new__

倘若(新式)类中绝非重写”__new__”方法,Python暗中认可是调用该类的第三手父类的”__new__”方法来协会该类的实例,如若此类的父类也向来不重写”__new__”,那么将直接依照同样的平整追溯至object的”__new__”方法,因为object是有所新式类的基类。

而假设新式类中重写了”__new__”方法,那么能够挑选随机2个其它的新式类(必须是新式类,唯有新型类有”__new__”,因为有着最新类都以从object派生)的”__new__”方法来创建实例,包蕴这几个新式类的有所前代类和后代类,只要它们不会招致递归死循环。

看一段例子代码:

classFoo(object):
  def__new__(cls,*args,**kwargs):
    obj=object.__new__(cls,*args,**kwargs) 
    # 这里的object.__new__(cls, *args, **kwargs)  等价于
    # super(Foo, cls).__new__(cls, *args, **kwargs) 
    # object.__new__(Foo, *args, **kwargs)
    # Bar.__new__(cls, *args, **kwargs)
    # Student.__new__(cls, *args, **kwargs),即使Student跟Foo没有关系,也是允许的,因为Student是从object派生的新式类

    # 在任何新式类,不能调用自身的“__new__”来创建实例,因为这会造成死循环
    # 所以要避免return Foo.__new__(cls, *args, **kwargs)或return cls.__new__(cls, *args, **kwargs)
    print"Call __new__ for %s"%obj.__class__
    returnobj  

classBar(Foo):
  def__new__(cls,*args,**kwargs):
    obj=object.__new__(cls,*args,**kwargs) 
    print"Call __new__ for %s"%obj.__class__
    returnobj 

classStudent(object):
  # Student没有“__new__”方法,那么会自动调用其父类的“__new__”方法来创建实例,即会自动调用 object.__new__(cls)
  pass

classCar(object):
  def__new__(cls,*args,**kwargs):
    # 可以选择用Bar来创建实例
    obj=object.__new__(Bar,*args,**kwargs) 
    print"Call __new__ for %s"%obj.__class__
    returnobj

foo=Foo()
bar=Bar()
car=Car()

代码的出口为:

澳门葡京备用网址 2

__init__的调用

“__new__”决定是不是要运用该类的”__init__”方法,因为”__new__”
能够调用其余类的构造方法恐怕间接重返其他类创造的目的来作为本类的实例。

平凡来讲,新式类起初实例化时,”__new__”方法会再次来到cls(cls指代当前类)的实例,然后调用该类的”__init__”方法作为起先化方法,该办法接收那个实例(即self)作为团结的首先个参数,然后逐一传入”__new__”方法中收取的地方参数和命名参数。

但是,如果”__new__”未有再次来到cls(即当前类)的实例,那么当前类的”__init__”方法是不会被调用的。

例子:

class A(object):
  def __init__(self, *args, **kwargs):
    print "Call __init__ from %s" %self.__class__

  def __new__(cls, *args, **kwargs):
    obj = object.__new__(cls, *args, **kwargs)
    print "Call __new__ for %s" %obj.__class__
    return obj  

class B(object):
  def __init__(self, *args, **kwargs):
    print "Call __init__ from %s" %self.__class__

  def __new__(cls, *args, **kwargs):
    obj = object.__new__(A, *args, **kwargs)
    print "Call __new__ for %s" %obj.__class__
    return obj   

b = B()
print type(b)

代码中,在B的”__new__”方法中,通过”obj = object.__new__(A,
*args,
**kwargs)”创立了3个A的实例,在那种处境下,B的”__init__”函数就不会被调用到。

澳门葡京备用网址 3

派生不可变类型

关于”__new__”方法还有三个人命关天的用途正是用来派生不可变类型。

举例说,Python中float是不行变类型,固然想要从float中派生二个子类,将在贯彻”__new__”方法:

classRound2Float(float):
  def__new__(cls,num):
    num=round(num,2)
    #return super(Round2Float, cls).__new__(cls, num)
    returnfloat.__new__(Round2Float,num)

f=Round2Float(4.14159)
printf

代码中从float派生出了一个Round贰Float类,该类的实例就是保留小数点后两位的浮点数。

通过内建函数dir(),大概访问类的字典属性__dict__,那两种格局都可以查看类有何样属性。

数码属性

类数据属性和实例数据属性

在上头的Student类中,”count””books””name”和”age”都被称为类的多少属性,可是它们又分为类数据属性和实例数据属性。

类变量紧接在类名前面定义,也等于java和c++的static变量

实例变量在__init__里定义,也正是java和c++的平凡变量

>>> class test:
         count = 0;类变量
        def __init__(self, c):
              self.count = c;
实例变量
             self.__class__.count = self.__class__.count + 1;

>>> a = test(3)
>>> a.count
3
>>> test.count
1

对于类数据属性和实例数据属性,能够计算为:

一.类多少属性属于类本身,可以通过类名实行走访/修改

二.类数目属性也得以被类的持有实例访问/修改

叁.在类定义之后,能够由此类名动态增加类数据属性,新扩充的类属性也被类和全体实例共有

四.实例数据属性只好通超过实际例访问

伍.在实例生成后,还足以动态增加实例数据属性,然而那几个实例数据属性只属于该实例

新鲜的类属性

对此有着的类,都有一组杰出的属性:

类属性 含义
__name__ 类的名字(字符串)
__doc__ 类的文档字符串
__bases__ 类的所有父类组成的元组
__dict__ 类的属性组成的字典
__module__ 类所属的模块
__class__ 类对象的类型

 Note:文书档案字符串对于类,函数/方法,以及模块来讲是并世无双的,也正是说__doc__品质是不可能从父类中持续来的。

属性隐藏

从下面的介绍理解到,类数据属性属于类自己,被抱有此类的实例共享;并且,通超过实际例能够去拜访/修改类属性。

而是,在通超过实际例中走访类属性的时候势须要深思远虑,因为大概出现属性”隐藏”的情形。

继续运用方面包车型大巴Student类,来看望属性隐藏:

wilber = Student(“Wilber”, 28)
 
print “Student.count is wilber.count: “, Student.count is wilber.count
wilber.count = 1   
print “Student.count is wilber.count: “, Student.count is wilber.count
print Student.__dict__
print wilber.__dict__
del wilber.count
print “Student.count is wilber.count: “, Student.count is wilber.count
 
print
 
wilber.count += 3   
print “Student.count is wilber.count: “, Student.count is wilber.count
print Student.__dict__
print wilber.__dict__
 
del wilber.count

print
 
print “Student.books is wilber.books: “, Student.books is wilber.books
wilber.books = [“C#”, “Python”]
print “Student.books is wilber.books: “, Student.books is wilber.books
print Student.__dict__
print wilber.__dict__
del wilber.books
print “Student.books is wilber.books: “, Student.books is wilber.books
 
print
 
wilber.books.append(“CSS”)
print “Student.books is wilber.books: “, Student.books is wilber.books
print Student.__dict__
print wilber.__dict__

代码的出口为:

澳门葡京备用网址 4

剖析一下下面代码的出口:

•对于不可变类型的类属性Student.count,能够通超过实际例wilber进行走访,并且”Student.count
is wilber.count”

•当通超过实际例赋值/修改count属性的时候,都将为实例wilber新建二个count实例属性,那时,”Student.count
is not wilber.count”

•当通过”del
wilber.count”语句删除实例的count属性后,再一次成为”Student.count is
wilber.count”

•一样对于可变类型的类属性Student.books,能够经超过实际例wilber举行走访,并且”Student.
books is wilber. books”

•当通过实例赋值books属性的时候,都将为实例wilber新建2个books实例属性,那时,”Student.
Books is not wilber. books”

•当通过”del wilber. books”语句删除实例的books属性后,再度成为”Student.
books is wilber. books”

•当通超过实际例修改books属性的时候,将修改wilber.books指向的内部存款和储蓄器地址(即Student.books),此时,”Student.
Books is wilber. books”

Note:
即便通超过实际例能够访问类属性,可是,不提出如此做,最棒照旧经过类名来访问类属性,从而幸免属性隐藏带来的不须要麻烦。

方法

在一个类中,恐怕现身三种办法,实例方法、静态方法和类方式,下边来探视二种艺术的例外。

实例方法

实例方法的第二个参数必须是”self”,”self”类似于C++中的”this”。

实例方法只可以由此类实例进行调用,那时候”self”就表示这么些类实例本人。通过”self”能够平昔访问实例的习性。

类方法

类情势以cls作为第五个参数,cls表示类本身,定义时利用@classmethod装饰器。通过cls可以访问类的有关属性。

class Student(object):
    ”’
    this is a Student class
    ”’
    count = 0
    books = []
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
    @classmethod
    def printClassInfo(cls):
        print cls.__name__
澳门葡京备用网址 ,        print dir(cls)
    pass
 
Student.printClassInfo()   
wilber = Student(“Wilber”, 28)
wilber.printClassInfo()

代码的出口为,从这段代码能够看到,类格局能够经过类名访问,也能够透超过实际例访问。

澳门葡京备用网址 5

静态方法

与实例方法和类情势分化,静态方法未有参数限制,既无需实例参数,也无需类参数,定义的时候利用@staticmethod装饰器。

同类格局相同,静态法能够通过类名访问,也足以经超过实际例访问。

class Student(object):
  '''
  this is a Student class
  '''
  count = 0
  books = []
  def __init__(self, name, age):
    self.name = name
    self.age = age

  @staticmethod
  def printClassAttr():
    print Student.count
    print Student.books
  pass

Student.printClassAttr()  
wilber = Student("Wilber", 28)
wilber.printClassAttr()

 

 

那三种方法的要紧不同在于参数,实例方法被绑定到多少个实例,只好通超过实际例进行调用;然而对于静态方法和类格局,可以通过类名和实例二种方法进行调用。

访问调节

Python中一直不访问调控的重视字,举例private、protected等等。

只是,在Python编码中,有一些预订来拓展访问调控。

“_”和” __”的采纳 越来越多的是一种标准/约定,不未有当真达到限制的目标:

“_”:以单下划线初叶的意味的是protected类型的变量,即只好同意其自己与子类进行访问;同时表示弱内部变量标示,如,当使用”from
moduleNmae import *”时,不会将以一个下划线起首的目的引进。
“__”:双下划线的象征的是个人类型的变量。只可以是同意这些类自个儿实行走访了,连子类也不能,那类属性在运作时属性名会加上单下划线和类名。

单下划线”_”

在Python中,通过单下划线”_”来兑现模块级其他私有化,一般约定以单下划线”_”初阶的变量、函数为模块私有的,相当于说”from
moduleName import *”将不会引进以单下划线”_”起始的变量、函数。

近期有一个模块lib.py,内容用如下,模块中2个变量名和2个函数名分别以”_”开头:

numA = 10
_numA = 100

def printNum():
  print "numA is:", numA
  print "_numA is:", _numA

def _printNum():
  print "numA is:", numA
print "_numA is:", _numA

当通过下边代码引进lib.py那些模块后,全部的以”_”伊始的变量和函数都未有被引进,若是访问将会抛出10分:

from lib import *
print numA
printNum()

print _numA
#print _printNum() 

澳门葡京备用网址 6

双下划线”__”

对此Python中的类属性,可以由此双下写道”__”来落到实处自然程度的私有化,因为双下写道初阶的质量在运维时会被”混淆”(mangling)。

在Student类中,参与了一个”__address”属性:

 

class Student(object):
  def __init__(self, name, age):
    self.name = name
    self.age = age
    self.__address = "Shanghai"

  pass

wilber = Student("Wilber", 28)
print wilber.__address 

 当通超过实际例wilber访问那几个性格的时候,就可以获取二个非凡,提醒属性”__address”不存在。

澳门葡京备用网址 7

其实,通过内建函数dir()就足以看来里边的有个别缘故,”__address”属性在运营时,属性名被改为了”_Student__address”(属性名前追加了单下划线和类名)

>>> wilber = Student("Wilber", 28)
>>> dir(wilber)
['_Student__address', '__class__', '__delattr__', '__dict__', '__doc__', '__form
at__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__r
educe__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '
__subclasshook__', '__weakref__', 'age', 'name']
>>> 

以说,即便是双下划线,也尚未兑现属性的私有化,因为经过上面包车型大巴章程照旧足以向来访问”__address”属性:

>>> wilber = Student("Wilber", 28)
>>> print wilber._Student__address
Shanghai
>>> 

双下划线的另八个器重的目地

防止子类对父类同名属性的争论。

看上面三个例子:

class A(object):
  def __init__(self):
    self.__private()
    self.public()

  def __private(self):
    print 'A.__private()'

  def public(self):
    print 'A.public()'

class B(A):
  def __private(self):
    print 'B.__private()'

  def public(self):
    print 'B.public()'

b = B()

当实例化B的时候,由于未有概念__init__函数,将调用父类的__init__,可是出于双下划线的”混淆”效果,”self.__private()”将变成
“self._A__private()”。

观察这里,就精通为啥会有如下输出了:

A.__private()

B.public()

上述那篇python类:class创立、数据格局属性及访问调节详解正是我分享给我们的全体内容了,希望能给大家贰个参照,也冀望大家多多匡助帮客之家。

在Python中,能够由此class关键字定义本身的类,然后通过自定义的类对象类…

  上边,小编就来总计一下自己的学习心得和学得的知识。

封装

装进:对表面世界隐藏对象的干活细节。

  1. 宣称三个类

做客可知性

在前头大家写了一个Student类,在那几个类中大家给目的绑定了name,school,age多个属性。在概念的时候我们采纳的是双下划线开头然后跟上变量名的方法去命名的。为啥要这么做呢?在python中方法和对象的访问权限和此外的编制程序语言C++、Java那一个事同样的,有二种访问权限既是个体的和公开的。,假使希望属性是私房的不容许外界对象访问,在给属性命名时能够用多少个下划线作为初阶。

Python在定义类的时候即使能够将质量设置为私有的,但是Python却尚未从语法上严厉管教个人属性或艺术的私密性,它只是给个体的个性和办法换了3个名字来“妨碍”对它们的造访,在领会命名规则的情状下任然能够访问到。由此当先1/3python程序员会遵循1种命名惯例正是让属性名以单下划线发轫来隐喻属性是受保证的。

说明:关于Python属性访问可知性的故事情节,参考致:http://blog.csdn.net/jackfrued/article/details/79513824

 

包装器 / 装饰器(decorator)

装饰格局有成都百货上千优良的运用境况,比如插入日志、品质测试、事务管理等等,有了装饰器,就足以领到大批量函数中与笔者坚守无关的好像代码,从而达到代码重用的目标。最大的收益正是能够让我们询问到函数内部到底发生了怎么样。前边学习了高阶函数,这里能够用高阶函数的知识写2个简练的装饰器:

def record(fn):
    def wrapper(*args, **kwargs):
        print('准备执行%s函数' % fn.__name__)
        # 执行被装饰的函数,在下面这行代码的前后我们可以附加其他的代码
        # 这些代码可以让我们在执行函数时做一下额外的工作
        val = fn(*args, **kwargs)
        print('%s函数执行完成' % fn.__name__)
        print('返回了val', val)
        # 返回被装饰函数的执行结果
        return val

    return wrapper

# 通过装饰器修饰f函数,让f函数在执行过程中可以做更多额外的操作
# 把@record放到f(n)函数的定义处,相当于执行了语句:f = record(f)  因此新的同名f函数就
# 指向了wrapper,调用f函数就是调用wrapper函数(且它原来的f函数不变)它的参数就变成了wrapper的参数
@record
def f(n):
    if n == 0 or n == 1:
        return 1
    else:
        return n * f(n - 1)


def main():
    f(5)


if __name__ == '__main__':
    main()

准备执行f函数
准备执行f函数
准备执行f函数
准备执行f函数
准备执行f函数
f函数执行完成
返回了val 1
f函数执行完成
返回了val 2
f函数执行完成
返回了val 6
f函数执行完成
返回了val 24
f函数执行完成
返回了val 120

通过下边包车型大巴这些案例大家得以直观的摸底到阶乘函数递归和回想的长河。
在Python中有七个放置的装饰器,都以跟class相关的:staticmethod、classmethod
和property。

  • staticmethod 是类静态方法,其跟成员方法的分化是未曾 self
    参数,并且可以在类不进行实例化的图景下调用
  • classmethod 与成员方法的分别在于所收受的第二个参数不是 self
    (类实例的指针),而是cls(当前类的求实项目)
  • property 是性质的意趣,表示能够通过通过类实例间接待上访问的音信!

class Triangle(object):
    def __init__(self, a, b, c):
        self._a = a
        self._b = b
        self._c = c

    # 类方法,同样的是发给类的消息,不是发给对象的消息
    @classmethod
    def is_valid2(cls, a, b, c):
        return a + b > c and b + c > a and a + c > b

    # 静态方法,是发送给类的消息,而不是发给对象的消息,使用方法如下
    @staticmethod
    def is_valid(a, b, c):
        return a + b > c and b + c > a and a + c > b

    @property
    def primeter(self):
        return self._a + self._b + self._c

    @property
    def area(self):
        half = self.primeter * 0.5
        return (half * (half - self._a) * (half - self._b) * (half - self._c)) ** 0.5


def main():
    a = 2
    b = 3
    c = 1
    if Triangle.is_valid(a, b, c):
        t1 = Triangle(a, b, c)
        print(t1.primeter)
        print(t1.area)
    else:
        print('不能构成三角形')

    if Triangle.is_valid2(a, b, c):
        t2 = Triangle(a, b, c)
        print(t2.primeter)
        print(t2.area)
    else:
        print('不能构成三角形')

    a = b = c = 5
    t3 = Triangle(a, b, c)
    print(t3.primeter)
    print(t3.area)




if __name__ == '__main__':
    main()

不能构成三角形
不能构成三角形
15
10.825317547305483

证实:类措施和静态方法都足以在未曾创制对象的图景下利用,可是累方法能够经过cls关键字访问到类的属性,而静态方法无法访问类的品质
property属性方法一般大家利用它来重临类的有些质量音信,而修改类属性的形式则是setter。使用setter以前必须有property,平时我们将property称之为查看器,setter称为修改器。

class Student(object):

继承

深信大家在定义类的时候一定蒙受过多少个一般的类的定义那种意况,举例定义一个猫类和1个狗类,在那中间他们都有大大小小,颜色,和跑,吃东西等特征,在这里面就能有繁多的再次代码,
马丁Fowler说过‘代码有许多中坏味道,重复是最坏的一种’所以有未有艺术来化解那种相似类出现重复代码的标题标点子呢?

要缓和这些主题素材就供给用到类的接轨了。在定义类的时候大家运用的是class关键字跟上类名和1对小括号,小括号内部正是咱们方今类承接的父类的名字,当然在近年来我们都写的是object,因为object能够是全数类的父类。对于地点的难题,有了承继大家就只必要定义3个父类,在父类少校子类的貌似的质量和格局定义好,子类去继承父类的艺术就能够去除掉这么些再一次代码了。示比如下:

class Animals(object):
    def __init__(self, name, color):
        self._name = name
        self._color = color

    def run(self):
        print('%s is running...' % self._name)

    def eat(self):
        print('%s is eating...' % self._name)

class Dog(Animals):
    def __init__(self, name, color, where):
        super().__init__(name, color) #指定name和color继承父类的初始化方法,当人默认就是继承父类,在子类有其他属性时,这一句指定继承父类的初始化方法的属性
        self._where = where

class Cat(Animals):
    def __init__(self, name, color, age):
        super().__init__(name, color)
        self._age = age

dog = Dog('jerry', 'black')
cat = Cat('Tom', 'white')
dog.run()
cat.eat()

地点代码的输出结果如下:

jerry is running...
Tom is eating...

在Python中类的持续一样的也匡助多三番4次,在多三番7回时,假设叁个措施在子类中绝非定义在四个父类都有定义,在调用方法的时候则是规行矩步从左往右的顺序调用第一个具备该方法的父类中定义的方式。当然这里是不提议利用多几次三番的。

  pass

艺术重写

子类在延续父类方法之后对章程进行了重新达成,就称为艺术重写。照旧用地点的例子,我们让狗跑三回只必要在Dog类里重写run方法就能够:

class Dog(Animals):
    def __init__(self, name, color, where):
        super().__init__(name, color)
        self._where = where

    def run(self):
        print('%s is running...twice' % self._name)

地点代码的出口结果如下:

jerry is running...twice
Tom is eating...

当子类对父类中的方法重写后,给子类对象发送实践那么些艺术的音信的时候是进行子类重写过后的措施,不是父类的措施。

注意:子类对象足以调用父类或然子类的大团结的法子,父类对象不能够调用子类的法子。

 

运算符重载

Python一样援助运算符重载,大家得以对类的专有方法实行重载,实比方下:

from math import gcd


class Fraction(object):

    def __init__(self, num, den):
        if den == 0:
            raise ValueError('分母不能为0') # raise表示引发一个值错误
        self._num = num
        self._den = den

    def __str__(self):
        if self._num == 0:
            return '0'
        elif self._den == 1:
            return self._num
        else:
            return '%d/%d' % (self._num, self._den)

    @property
    def den(self):
        return self._den

    @property
    def num(self):
        return self._num

    def add(self, other):
        return Fraction(self._num * other.den + \
                        other.num * self._den, self._den * other.den)

    # 运算符重写:
    # 即是在做运算的时候可以直接使用符号即可获得相应的结果
    def __add__(self, other):
        return self.add(other)

    def sub(self, other):
        return Fraction(self._num * other.den - \
                        other.num * self._den, self._den * other.den)

    def __sub__(self, other):
        return self.sub(other)

f1 = Fraction(-3,5)
f2 = Fraction(1,2)
print(f1.add(f2))
print(f1.sub(f2))
print(f1 + f2)
print(f1 - f2)

程序执行结果如下:

-1/10
-11/10
-1/10
-11/10

 

多态

class   是申明类的主要字,Student  是类名称。括号之中 object
是在接二连三的时候才用的,如若未有承继其余类,就能够继承object类。

抽象类

抽象类是含有抽象方法的类,而空虚方法不分包其余可达成的代码,只可以在其子类中落实抽象函数的代码。Python并未从言语层面帮助抽象类概念,能够透过abc模块来制作抽象类的效用。由此在Python中要达成抽象类在此以前要求导入abc模块中的元类(ABCMeta)和装饰器(abstractmethod)。

  • 元类(ABCMeta)

在创制抽象类时使用metaclass=ABCMeta表示将该类创设为抽象类,metaclass=ABCMeta钦点该类的元类是ABCmeta。所谓元类正是创造类的类。

  • 装饰器(abstractmethod)

在定义方法的时候利用这一个装饰器包装,将制定的办法定义为架空方法。

因为虚无方法不含有其余可完成的代码,因而其函数体日常使用pass。上边演示抽象类的达成和多态。所谓的多态指的是在抽象类中定义叁个情势,能够在其子类中另行达成,差异子类中完成的方法也不尽一样。

"""
某公司有三种类型的员工 分别是部门经理、程序员和销售员
需要设计一个工资结算系统 根据提供的员工信息来计算月薪
部门经理的月薪是每月固定15000元
程序员的月薪按本月工作时间计算 每小时150元
销售员的月薪是1200元的底薪加上销售额5%的提成
"""
from abc import ABCMeta, abstractmethod

class Employee(object, metaclass=ABCMeta):

    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name

    @abstractmethod  # 将该方法定义为抽象方法,强制子类实现get_salary方法
    def get_salary(self):
        pass


class Manager(Employee):

    def get_salary(self):
        return 15000


class Programmer(Employee):

    def __init__(self, name):
        super().__init__(name)
        self._working_hour = 0

    @property
    def working_hour(self):
        return self._working_hour

    @working_hour.setter
    def working_hour(self, hour):
        self._working_hour = hour if hour > 0 else 0

    def get_salary(self):
        return 150.0 * self._working_hour

class Salesman(Employee):

    def __init__(self, name, sales=0):
        super().__init__(name)
        self._sales = sales

    @property
    def sale(self):
        return self._sales

    @sale.setter
    def sale(self, sale):
        self._sales = sale if sale > 0 else 0

    def get_salary(self):
        return self._sales * 0.05 + 1200.0


def main():
    emps = [Manager('令狐冲'), Programmer('东方不败'),
            Manager('岳不群'), Salesman('林平之'),
            Salesman('风清扬'), Programmer('仪琳师妹'),
            ]

    for emp in emps:
        if isinstance(emp, Programmer):  # 识别对象的类型,判断给定的对象是否是后面给的类型
            emp.working_hour = int(input('请输入%s本月工作时间:' % emp.name))
        if isinstance(emp, Salesman): 
            emp.sale = int(input('请输入%s本月销售金额:' % emp.name))
        # 同样是调用get_salary()方法,但是不同的员工做出了不同行为
        # 因为三个子类都重写了get_salary()方法,所以此处有多态行为
        print('%s本月工资为:¥%.2f元' % (emp.name, emp.get_salary()))


if __name__ == '__main__':
    main()

令狐冲本月工资为:¥15000.00元
请输入东方不败本月工作时间:25
东方不败本月工资为:¥3750.00元
岳不群本月工资为:¥15000.00元
请输入林平之本月销售金额:15000
林平之本月工资为:¥1950.00元
请输入风清扬本月销售金额:5
风清扬本月工资为:¥1200.25元
请输入仪琳师妹本月工作时间:56
仪琳师妹本月工资为:¥8400.00元

注意:

壹.抽象类不可能创立对象(正是无法实例化),抽象类存在的含义是专程拿给任何类承继的。

2.类在尚未抽象方法的时候不是抽象类能够实例化,有抽象方法的时候就算抽象类不可能举行实例化

三.当子类覆盖了父类的虚幻方法的事后,子类就不是抽象类了,就足以实例化,当子类未有掩盖父类的指雁为羹方法,从父类承袭的时候子类也是抽象类,不可能实例化

4.架空方法 必须在子类进行重写,不然就能够报错

pass区域是类的方法和属性

 

私家属性大概措施:私有属性也许措施是以双下划线开头的(_
_XXX),这几个天性正是不得不类本身内部访问,子类也许类的表面是不能访问的。

受保险属性只怕措施:受保证的属性和方式是指只好通过类和子类进行访问,格式是以单下划线初叶的(_XXXX)。

 

  1. 上边,大家来创制3个全体的类

 

class Student(object):
    name=""  # 这个是类的属性
    age=""  # 这个也是累的属性
    __score=""    # 这个是类的私有属性,不能直接在类的外部进行访问,只能通过类的内部方法进行访问。

    def __init__(self,name,age,score): # 这个是类的构造方法
        self.name=name
        self.age=age
        self.__score=score     # 这个是私有属性,子类是没有办法访问的,只能自己使用

    def print_info(self): #这个是类的方法
        print(self.name)
        print(self.age)
        print(self.__score)  # 这样就是使用的类的内部方法访问私有属性

  def __age_change(self):              # 这个方法是类的私有方法,在内的外部无法进行访问,调用方式就是在类的内部在创建一个公有的方法来调用私有方法执行

      print("my love ")

  def use_age_change(self):   # 这方法就是用来调用私有方法的公有方法
      self.__age_change()

ins_zrs=Student("zhangrongshun",18,100)   # 实例的创建
ins_zrs.print_info()  # 用实例来调用方法

 

那便是类的创设到实例化的欧洲经济共同体步骤。

 

类的构造方法的职能:正是用来早先化对象的习性的

 

上边正是累的存在延续了,python里面包车型客车类帮衬单承接和多承袭,可是php只帮助单承接,学习过php的同学应该都清楚啊。

#这个类将会继承上面的类-----单继承
class U_student(Student):
    grade=""  # 在子类中新增加一个属性
    def __init__(self,name,score,age,grade):
        Student.__init__(self,name,score,age)   # 这个是Student的
        self.grade=grade

    def print_information(self):
        print(self.name)
        print(self.grade)
        print(self.age)

    def _p_name(self):
        print("li hai ")

d=U_student("zhangrongshun",88,22,6)
d.print_information()

# 注意 在继承类的属性的时候私有属性是不能被继承的

 

相关文章

发表评论

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

*
*
Website