博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(P36-P41)对象:OO特征,self ,__init__ ,公有和私有 ,继承 ,类的组合关系 ,类、类对象和实例对象 ,BIF,构造和析构
阅读量:4299 次
发布时间:2019-05-27

本文共 9086 字,大约阅读时间需要 30 分钟。

文章目录

1.对象

  • 在win下如何调试使用python写好的一个类?
    使用IDLE打开python代码
    在这里插入图片描述
    执行Run中的Run Module调试写好的类
    在这里插入图片描述
  • test.py代码如下:
class Turtle: # Python 中的类名约定以大写字母开头    """关于类的一个简单例子"""    # 属性    color = 'green'    weight = 10    legs = 4    shell = True    mouth = '大嘴'    # 方法    def climb(self):        print("我正在很努力的向前爬......")    def run(self):        print("我正在飞快的向前跑......")    def bite(self):        print("咬死你咬死你!!")    def eat(self):        print("有得吃,真满足^_^")    def sleep(self):        print("困了,睡了,晚安,Zzzz")
  • 对象中的属性和方法,在编程中实际是变量(属性)和函数(方法)。

2.OO特征

  • OO(面向对象)的特征
    封装:对外部隐藏对象的工作细节
    继承:子类自动共享父类之间数据和方法的机制
    多态:可以对不同类的对象调用相同的方法,产生不同的效果
定义一个带列表类MyList,继承list,则列表的功能它都可以使用>>> class MyList(list):    pass>>> list2 = MyList()>>> list2.append(5)>>> list2.append(6)>>> list2.append(1)>>> list2[5, 6, 1]>>> list2.sort()>>> list2[1, 5, 6]

3.self

  • 要求:在类定义的时候,将self写入到第一个参数

  • Python的self其实就相当于C++的this指针。由同一个类可以生产无数对象,当一个对象的方法被调用的时候,对象会将自身的引用作为第一个参数传给该方法,那么python就知道需要操作哪个对象的方法了。

  • eg:

>>> class Ball:    def setName(self,name):        self.name = name    def kick(self):        print('我叫%s,该死的,谁踢我。。。' % self.name)        >>> a = Ball()>>> a.setName('球A')>>> b = Ball()>>> b.setName('球B')>>> a.kick()我叫球A,该死的,谁踢我。。。>>> b.kick()我叫球B,该死的,谁踢我。。。

4.__init__

  • python的这些具有魔法的方法,总是被双下划线所包围,例如__init__(),即构造方法,也称构造函数,这个方法会在对象被创建时自动调用。其实,实例化对象时是可以传入参数的,这些参数会自动传入__init__()方法中,可以通过重写这个方法来自定义对象的初始化操作

  • eg:

>>> class Ball():    def __init__(self,name):        self.name = name    def kick(self):        print('我叫%s,该死的,谁踢我。。。' % self.name)        >>> b = Ball('小土豆')>>> b.kick()我叫小土豆,该死的,谁踢我。。。

5.公有和私有

  • 为了实现定义私有变量,只需要在变量名或函数名前加上"__"两个下划线,那么这个函数或变量就会变成私有的了:
>>> class Person:    __name = '亦我飞也'    def getName(self):        return self.__name    >>> p = Person()>>> p.__nameTraceback (most recent call last):  File "
", line 1, in
p.__nameAttributeError: 'Person' object has no attribute '__name'>>> p.getName()'亦我飞也'
  • pyton的私有变量其实是伪私有
    实际上在外部使用“_类名__变量名“即可访问双下划线开头的私有变量了
>>> p._Person__name'亦我飞也'

6.继承

  • 继承方法
class DerivedClassName(BaseClassName):
  • 一个子类可以继承它的父类的所有属性和方法
>>> class Parent:    def hello(self):        print('正在调用父类的方法。。。')        >>> class Child(Parent):    #子类继承父类    pass     #直接往下执行>>> p = Parent()>>> p.hello()正在调用父类的方法。。。>>> c = Child()>>> c.hello()正在调用父类的方法。。。
  • 如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法和属性(即子类方法属性改变,父类是不变的)
    解决办法:
    (1)调用未绑定的父类方法
    (2)使用super函数(推荐使用,因为只需要改派生类中的参数:基类名字就行了,不需要按照(1)要改很多Fish.init(self)中的Fish)
import random as rclass Fish:    def __init__(self):        self.x = r.randint(0,10)        self.y = r.randint(0,10)    def move(self):        self.x -= 1        print('我的位置是:',self.x,self.y)class Goldfish(Fish):    passclass Garp(Fish):    passclass Shark(Fish):    def __init__(self):    	Fish.__init__(self)  ##(1)调用未绑定的父类方法,self是子类的实例对象        self.hungry = True    def eat(self):        if self.hungry:            print('吃货的梦想就是天天有的吃')            self.hungry = False        else:            print('太撑了,吃不下了!')Fish.__init__(self)  ##(1)调用未绑定的父类方法,self是子类的实例对象其实就是>>>Fish.__init__(shark)>>>shark.move()我的位置是:3 6使用super函数(super函数会帮我们自动找到基类的方法,而且还自动为我们传入self参数)Fish.__init__(self) 改为super().__init__
  • 多重继承:不建议使用
class DerivedClassName(Base1, Base2, Base3):……实例:子类c同时继承基类Base1和基类Base2>>> class Base1:    def fool1(self):        print('我是fool1,我为Base1代言。。。')        >>> class Base2:    def fool2(self):        print('我是fool2,我为Base2代言。。。')        >>> class C(Base1,Base2):    pass>>> c = C()>>> c.fool1()我是fool1,我为Base1代言。。。>>> c.fool2()我是fool2,我为Base2代言。。。

7.类的组合关系

  • 组合(将需要的类一起进行实例化并放入新的类中),非继承关系的几个类放到一起
  • eg:
class Turtle:    def __init__(self,x):        self.num = xclass Fish:    def __init__(self,x):        self.num = xclass Pool:    def __init__(self,x,y):        self.turtle = Turtle(x)        self.fish = Fish(y)    def print_num(self):        print('水池里一共有乌龟 %d 条,鱼 %d 条' % (self.turtle.num,self.fish.num))>>> pool = Pool(5,2)>>> pool.print_num()水池里一共有乌龟 5 条,鱼 2 条

8.类、类对象和实例对象

  • 类、类对象和实例对象
    在这里插入图片描述
  • eg:以下例子可见,对实例对象c的count属性赋值后,就相当于覆盖了类对象C的count属性。如果没有赋值覆盖,那么引用的是类对象的count属性
class C:	count = 0;>>> a = C()>>> b = C()>>> c = C()>>> print(a.count,b.count,c.count)0 0 0>>> c.count += 10>>> print(a.count,b.count,c.count)0 0 10>>> C.count += 100>>> print(a.count,b.count,c.count)100 100 10
  • 另外,如果属性的名字跟方法名相同,属性会覆盖方法:
    结论:不要试图在一个类里边定义出所有能想到的特性和方法,应该利用继承和组合机制来进行扩展;用不同的词性命名,如属性名用名词、方法名用动词,并使用骆驼命名法等。
>>> class C:    def x(self):        print('X-man')        >>> c = C()>>> c.x()X-man>>> c.x = 1              #新定义对象c的一个x属性,并赋值为1>>> c.x1>>> c.x()     #可见,方法x()已经被属性x给覆盖了Traceback (most recent call last):  File "
", line 1, in
c.x()TypeError: 'int' object is not callable
  • eg:到底什么是绑定?
    python严格要求需要有实例才能被调用,即绑定概念
>>> class BB:    def printBB():        #缺少self,导致无法绑定具体对象        print('no zuo no die')        >>> BB.printBB()no zuo no die>>> bb = BB()>>> bb.printBB()        #出现错误原因是由于绑定机制,自动把bb对象作为第一个参数传入,实际:bb.printBB(bb)Traceback (most recent call last):  File "
", line 1, in
bb.printBB()TypeError: printBB() takes 0 positional arguments but 1 was given
  • 测试:
    实例对象叫dd,类对象叫CC,类也叫CC;
    dd.__dict__显示实例对象属性;
    CC.__dict__显示类对象属性,但不显示魔法方法;
    类中定义的属性,方法是静态变量。就算类对象被删除了,他们依旧是存放在内存中的。只有在程序退出的时候,该静态变量才会被释放。
    大多数情况下,应该考虑使用实例属性,self.x相当于dd.x,self相当于实例的名字,.什么相当于实例的空间了。类属性仅仅用来跟踪与类相关的值。
    在这里插入图片描述

9.与类和对象相关的一些相关的BIF

  • issubclass(class, classinfo)
    如果第一个参数是第二个参数的一个子类,则返回True,否则返回False:
    1️⃣一个类被认为是其自身的子类。
    2️⃣classinfo可以是类对象组成的元组,只要class是其中任何一个候选类的子类,则返回True。
    3️⃣在其他情况下,会抛出一个TypeError异常。
>>> class A:    pass>>> class B(A):    pass>>> issubclass(B,A)True>>> issubclass(B,B)   #一个类被认为是其自身的子类True>>> issubclass(B,object)      # object是所有类的基类True>>> class C:    pass>>> issubclass(B,C)False
  • isinstance(object, classinfo)
    如果第一个参数是第二个参数的实例对象,则返回True,否则返回False:
    1️⃣如果object是classinfo的子类的一个实例,也符号条件。
    2️⃣如果第一个参数不是对象,则永远返回False。
    3️⃣classinfo可以是类对象组成的元组,只要object是其中任何一个候选对象的实例,则返回True。
    4️⃣如果第二个参数不是类或者由类对象组成的元组,会抛出一个TypeError异常。
>>> issubclass(B,C)       注:第一个参数如果不是对象,则永远返回FalseFalse>>> b1 = B()>>> isinstance(b1,B)True>>> isinstance(b1,C)False>>> isinstance(b1,A)True>>> isinstance(b1,(A,B,C))True
  • hasattr(object, name)
    attr即attribute的缩写,属性的意思。其作用就是测试一下对象里是否有指定的属性。
    第一个参数是对象,第二个参数是属性名(属性的字符串名字),举个例子:
>>> class C:    def __init__(self,x=0):        self.x = x        >>> c1 = C()>>> hasattr(c1,'x')    #注意,属性名要用引号括起来True
  • getattr(object, name[, default])
    返回对象指定的属性值,如果指定的属性不存在,则返回default(可选参数)的值;若没有设置default参数,则抛出AttributeError异常。
>>> class C:    def __init__(self, x=0, y=1):        self.x = x        self.y = y>>> c1 =C()>>> getattr(c1, 'x')0>>> getattr(c1, 'y')1>>> getattr(c1, 'z')Traceback (most recent call last):  File "
", line 1, in
getattr(c1, 'z')AttributeError: 'C' object has no attribute 'z'>>> getattr(c1, 'z', '您访问的属性不存在')'您访问的属性不存在'
  • setattr(object, name, value)
    用来设置对象中指定属性的值,如果指定的属性不存在,则新建属性并赋值。
>>> setattr(c1,'y','FishC')>>> getattr(c1,'y')'FishC'
  • elattr(object, name)
    用来删除对象中指定的属性,如果属性不存在,则抛出AttributeError异常。
>>> delattr(c1,'y')>>> delattr(c1,'Z')Traceback (most recent call last):  File "
", line 1, in
delattr(c1,'Z')AttributeError: Z
  • property(fget=None, fset=None, fdel=None, doc=None)
    用来通过属性来设置属性。
>>> class C:    def __init__(self,size =10):        self.size = size    def getSize(self):        return self.size    def setSize(self,value):        self.size = value    def delSize(self):        del self.size    x=property(getSize,setSize,delSize)    >>> c = C()>>> c.x         #调用getSize()10>>> c.x = 12      #调用x=property(getSize,setSize,delSize)>>> c.x12>>> c.size12>>> del c.x      #删除属性x()>>> c.sizeTraceback (most recent call last):  File "
", line 1, in
c.sizeAttributeError: 'C' object has no attribute 'size'
  • property()函数中的三个函数分别对应的是获取属性的方法、设置属性的方法以及删除属性的方法,这样一来,外部的对象就可以通过访问x的方式,来达到获取、设置或删除属性的目的。
    当需要更改上例中的getSize、setSize或delSize函数的名称时,如果这些方法是作为接口让用户调用的,那么对用户而言就要修改自己调用的方法名,很麻烦,使用了proprty()后,用户就不需担心这种问题了。

10.构造和析构

  • 两个构造方法
    (1)__ init__(self[,…])
    这个方法一般用于初始化一个类。
    但是,当实例化一个类的时候, __ init__()并不是第一个被调用的, 第一个被调用的是__ new__()。
>>> class Rectangle:    def __init__(self,x,y):        self.x = x        self.y = y    def getPeri(self):        return (self.x + self.y) * 2    def getArea(self):        return self.x * self.y>>> rect = Rectangle(5,2)>>> rect.getPeri()14>>> rect.getArea()10

一般在需要进行初始化的时候才重写__ init__()方法。而且要记住该方法的返回值一定是None(或者也可以理解没有返回值)。

  • 两个构造方法
    (2)__ new__(cls[,…])重写基类方法
    __ new__()方法是创建类实例的方法, 创建对象时调用, 返回当前对象的一个实例。
    下面是当继承一个不可变的类型的时候,它的特征就显得尤为重要了。
    其实,new()才是在一个对象实例化时候所调用的第一个方法,它的第一个参数是这个类(cls),而其他的参数会直接传递给__init__()方法
__new__(cls[, ...])>>> class CapStr(str):    def __new__(cls,string):        string = string.upper()        return str.__new__(cls,string)    >>> a = CapStr('hello world')>>> a'HELLO WORLD
  • del(self) 当对象将要被销毁的时候,这个方法就会被调用。但要注意,并非del x就相当于调用x.del()。
    (1)Python中的垃圾回收是以引用计数为主,分代收集为辅。引用计数的缺陷是循环引用的问题。
    (2)在Python中,如果一个对象的引用数为0,Python虚拟机就会回收这个对象的内存。
>>> class C:    def __init__(self):        print('我是__init__方法,我被调用了...')    def __del__(self):        print('我是__del__方法,我被调用l...')        >>> c1 = C()     #创建对象c1我是__init__方法,我被调用了...>>> c2 = c1>>> c3 = c2>>> del c1>>> del c2>>> del c3   #删除c3时,对象c1才会彻底被删除(即没有标签指向对象c1时,其才会被回收),引用计数=0时被删除我是__del__方法,我被调用l...
  • 参考:,,

转载地址:http://tliws.baihongyu.com/

你可能感兴趣的文章
Hbase进阶
查看>>
hbase架构原理之region、memstore、hfile、hlog、columm-family、colum、cell(有时间看)
查看>>
MemStore作用及flush过程
查看>>
HBase----Region Server架构
查看>>
Apache Sqoop-----hdfs迁移工具
查看>>
Sqoop往Hive导入数据实战
查看>>
Mysql到HBase的迁移
查看>>
Sqoop import进阶
查看>>
Hive语句是如何转化成MapReduce任务的
查看>>
Hive创建table报错:Permission denied: user=lenovo, access=WRITE, inode="":suh:supergroup:rwxr-xr-x
查看>>
Hive执行job时return code 2排查
查看>>
hive常用函数及数据结构介绍
查看>>
Hive面试题干货(亲自跟着做了好几遍,会了的话对面试大有好处)
查看>>
MapReduce排查错误日志方法
查看>>
力扣题解-648. 单词替换
查看>>
力扣题解-211. 添加与搜索单词 - 数据结构设计
查看>>
力扣题解-589. N叉树的前序遍历(递归和迭代)
查看>>
力扣题解-589. N叉树的后序遍历
查看>>
力扣题解-429. N叉树的层序遍历(广度优先搜索)
查看>>
力扣题解-112. 路径总和(分治法思想,递归的方式求解)
查看>>