类和对象

类和对象

类名以大写字母开头, 对象 = 属性(静态) + 方法(动态)
类的实例化:tt = Turtle(),那么tt就是turtle的一个实例对象
调用内部方法:tt.climb(), tt.sleep()
OO = Object Oriented 面向对象:封装、继承、多态
继承:class Mylist(list) # 这个Mylist类继承了list的方法,所以用Mylist定义的新的对象,有list的方法

class Mylist(list):
	pass

list2 = Mylist()
list2.appen(0)
list2.append(7)
list2.append(5)
print(list2)

多态: 不同对象具有不同的方法,例如在两个不同的类中有同样名字的方法函数,那么调用的时候,是按照自己类里面的定义进行实现的

self: 相当于C++的this指针

self:在Python类中规定,函数的第一个参数是实例对象本身,并且约定俗成,把其名字写为self。其作用相当于java中的this,表示当前类的对象,可以调用当前类中的属性和方法。

class Ball:
	def setName(self, name):
		self.name = name
	def kick(self):
		print("who kicked me?")

a = Ball()
a.setName('ball_A')
b = Ball()
b.setName('ball_B')
c = Ball()
c.setName('ball_C')

init(self):构造方法:

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

init()函数:相当于私有的,对象实例化时,首先自动运行的函数,并且可以使类带上参数。
在Python中定义类经常会用到__init__函数(方法),首先需要理解的是,两个下划线开头的函数是声明该属性为私有,不能在类的外部被使用或访问。
__init__函数(方法)支持带参数类的初始化,也可为声明该类的属性(类中的变量)。__init__函数(方法)的第一个参数必须为self,后续参数为自己定义。

class Box:
#def setDimension(self, width, height, depth):
# self.width = width
# self.height = height
# self.depth = depth
def __init__(self, width, height, depth):
	self.width = width
	self.height = height
	self.depth = depth

def getVolume(self):
	return self.width * self.height * self.depth

b = Box(10, 20, 30)
print(b.getVolume())

公有和私有

默认:对象的属性和方法是公有的
私有变量或者函数只需要在变量名前加上“__”,两个下划线,就会变成私有,如果要调用,可以在类的内部设置公有的调用函数,或者明白Python的私有化的方式,p._Person__name也可以访问

继承

class Derived ClassName(BaseClassName1[, BaseClassName2[, BaseClassName3, …):支持多重继承
子类继承父类的所有属性和方法,但是如果子类定义了新的相同的属性或者方法,则不会再继承父类的

# -*- coding: UTF-8 -*-
# Created by cdh at 2020/6/25
import random


class Fish:
    def __init__(self):
        [self.x,self.y] = [random.randint(0, 10), random.randint(0, 10)]


    def move(self):
        self.x -= 1
        print("我的位置是:",self.x, ',', self.y)


class Goldfish(Fish):
    pass


class Carp(Fish):
    pass


class Salmon(Fish):
    pass


class  Shark(Fish):
    def __init__(self):
        self.hungry = True


    def eat(self):
        if self.hungry:
            print("天天吃东西")
            self.hungry = False
        else:
            print("我现在很饱")

以上代码会在Shark实例化对象调用move()方法时报错,因为shark 子类的__init__()方法会将父类的覆盖,以至于没有x, y的坐标

**调用未绑定的父类方法:**在子类的方法定义__init__()时候,为了防止将父类的方法__init__覆盖掉,在子类的__init__()方法中加入代码:Fish.init(self)。
意思是我定义子类的__init__()的时候,先调用父类的 init()函数,实例化对象的self是shark的,也就是说,我先通过父类的__init__()将子类的self初始化一下“Fish.init(self)”,再继续独有的初始化“self.hungry = True”

未绑定是指:“Fish.init(self)”中的self是子类的不是父类的,就是Fish.init(self),函数是父类的,self是子类的

修改后的代码如下:

class  Shark(Fish):
    def __init__(self):
    	Fish.__init__(self)
        self.hungry = True

使用super方法:
只需要在定义覆盖之前,通过“super().需要的即将被覆盖的父类函数名()”语句就可以实现继承将被覆盖的方法;如果涉及多个相同的集成,则会广度优先遍历:https://fishc.com.cn/thread-48759-1-2.html
支持多重继承:所有基类中的方法

class  Shark(Fish):
    def __init__(self):
    	super().__init__()
        self.hungry = True

组合

将已经定义的类 在新定义的类里面 实例化后组合使用,即新类的一个属性为旧类的实例化对象,也就是将旧类的实例化放到新类里面
相当于新定义一个函数的时候使用已经定义好的函数(函数的嵌套)。
针对于没有直接继承关系的

import random


class Turtle:
    def __init__(self, x):
        self.num = x
    

class Fish:
    def __init__(self, x):
         self.num = x


class 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(1, 10)
>>> pool.print_num()
水池里有鱼:1条,乌龟10只!

类、类对象、实例对象:

类定义好了以后本身就是类对象,类的实例化就是实例对象。
可以通过类对象修改类的属性,那么所有的实例中包含类对象属性都会被修改
可以通过实例化对象修改单个实例的属性,这个步骤会创建一个相同名字的属性,将实例的属性独立出来,想再通过更改类对象属性改变实例属性,就不可能实现了

>>> class B:
	count = 0

	
>>> a = B()
>>> b = B()
>>> c = B()
>>> a.count
0
>>> b.count
0
>>> c.count
0
>>> a.count += 10
>>> a.count
10
>>> B.count += 1000
>>> a.count
10
>>> b.count
1000
>>> c.count
1000

属性和方法名相同时,属性会覆盖方法
Python严格要求,方法需要有实例才能被调用,这就叫绑定的概念 ,即不要去用类对象调用方法

一些相关的内置函数(BIF)

  1. issubclass(class, classinfo):自身子类检查,class是否是classinfo的子类;class本身是自己的子类,classinfo可以是class组成的元组,候选类是否是元组的子类
>>> 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
>>> issubclass(A, B)
False
  1. isinstance(object, classinfo):实例对象是否是属于类元组(考虑继承关系),object是实例对象,classinfo可以是元组,如果object不是对象,则返回False, classinfo不是类的话,则报错
  2. hasattr(object, name):测试对象是否有指定的属性,name 是字符串形式
  3. getattr(object, name[, default]):返回对象指定的属性值,如果不存在,则返回default,如果没设置,则抛出异常
  4. setattr(object, name, value): 访问某个属性并且赋值,如果不存在则自动创建并设置为value值
  5. delattr(object, name):删除指定属性,如果没有这个属性则抛出异常
  6. property(fget=None, fset=None, fdel=None, doc=None):属性设置属性。fget、fset、fdel 分别为获取属性、设置属性、删除属性的三个方法,需要自己编写,当x = property(g, s, d)后,c.x直接会调用第一个方法,c.x = 2时候,会自动那个调用第二个方法,del c.x 会自动调用第三个方法。
    测试代码:
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)

测试结果:

>>> c1 = C()
>>> c1.size
10
>>> c1.getSize()
10
>>> c1.x
10
>>> c1.x = 18
>>> c1.x
18
>>> c1.size
18
>>> del c1.x
>>> c1.size
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    c1.size
AttributeError: 'C' object has no attribute 'size'

修饰器

https://www.jianshu.com/p/ab702e4d4ba7
修饰符的作用就是为已经存在的对象添加额外的功能,经常被用于有切面需求的场景

def bread(func) :  
    def wrapper() :  
        print "</'''       '''\>"  
        func()  
        print "<\______/>"  
    return wrapper  
   
def ingredients(func) :  
    def wrapper() :  
        print "#tomatoes#"  
        func()  
        print "~salad~"  
    return wrapper  
   
def sandwich(food="--ham--") :  
    print food  
   
sandwich()  
#输出 : --ham--  
sandwich = bread(ingredients(sandwich))  
sandwich()  

#输出:  

#</'''       '''\>  
# #tomatoes#  
# --ham--  
# ~salad~  
#<\______/>  

语法糖:

def bread(func) :  
    def wrapper() :  
        print "</'''       '''\>"  
        func()  
        print "<\______/>"  
    return wrapper  
   
def ingredients(func) :  
    def wrapper() :  
        print "#tomatoes#"  
        func()  
        print "~salad~"  
    return wrapper  

@bread  
@ingredients  
def sandwich(food="--ham--") :  
    print food  
   
sandwich()

## 静态方法补充说明
静态方法是类中的函数,不需要实例。静态方法主要是用来存放逻辑性的代码,主要是一些逻辑属于类,但是和类本身没有交互,即在静态方法中,不会涉及到类中的方法和属性的操作。可以理解为将静态方法存在此类的名称空间中。

```python
class Myclass:
    # 实例方法
    def instancemethod(self):
        print("我是实例方法")
    # 静态方法
    @staticmethod
    def staticmethod():
        print("我变成静态了")
    # 类方法
    @classmethod
    def classmethod(self):
        print("我已经是类方法了")

a = Myclass()
'Myclass.instancemethod() # 这个访问是不允许的,因为是属于实例方法,其他两个同理'
Myclass.classmethod() # 这个是正确的,因为已经修饰为类方法了
Myclass.staticmethod() # 这个也是被允许的,因为已经是静态方法了

# 以下三个调用都是被允许的,是通过实例对象的调用
a.instancemethod()
a.staticmethod()
a.classmethod()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值