python的类和对象_Python学习笔记——类和对象

类和对象

1. 一个例子

# 对象 = 属性 + 方法

# Python 中的类名称约定首字母大写,而 Python 函数名首字母小写

class Turtle:

#属性

color = 'green'

weight = 10

legs = 4

shell = True

mouth = '大嘴'

# 方法

# 这里的 self 表示 this 指针

def climb(self):

print("我正在很努力地向前爬")

def run(self):

print("我正在飞快地向前跑")

def bite(self):

print("我咬死你咬死你")

def eat(self):

print("有得吃,真满足!")

def sleep(self):

print("困了,睡觉,晚安")

tt = Turtle()

tt.climb()

tt.bite()

tt.sleep()

我正在很努力地向前爬

我咬死你咬死你

困了,睡觉,晚安

2. 面向对象的特征

① 封装

# 我们只知道这些方法如何调用,并不知道方法内部怎么实现的

list1 = [2,1,7,5,3]

list1.sort()

list1.append(9)

print(list1)

[1, 2, 3, 5, 7, 9]

② 继承

class MyList(list): # 这里表示 Mylist 类继承于 list 类

# pass 为占位符,表明不做任何操作

pass

list2 = MyList()

# list 类中的方法都被继承了

list2.append(1)

list2.append(7)

list2.append(5)

list2.append(4)

list2.append(9)

list2.sort()

print(list2)

[1, 4, 5, 7, 9]

③ 多态

# 不同对象对同一方法响应不同的行动

class A:

def fun(self):

print("我是小A")

class B:

def fun(self):

print("我是小B")

a = A()

b = B()

a.fun()

b.fun()

我是小A

我是小B

3. self

# 当一个对象的方法被调用时,会将自身作为参数传入

# 类的方法定义时,必须把 self 写入第一个参数

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')

c = Ball()

c.setName('球C')

a.kick()

b.kick()

c.kick()

我叫球A,该死的,谁踢我。。。

我叫球B,该死的,谁踢我。。。

我叫球C,该死的,谁踢我。。。

4. _ _ init _ _ (self)(这里是两个双下划线)

class Ball:

# 这个即为构造函数

def __init__(self,name):

self.name = name

def kick(self):

print("我叫%s,该死的,谁踢我。。。" % self.name)

b = Ball('土豆')

b.kick()

我叫土豆,该死的,谁踢我。。。

5. 公有和私有

class Person:

name = '小甲鱼'

p = Person()

print(p.name)

小甲鱼

class Person:

# 变量前加上双下划线就会变成私有变量,无法直接调用

__name = '小甲鱼'

# 可以通过方法来调用

def getName(self):

return self.__name

p = Person()

print(p.name)

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

AttributeError Traceback (most recent call last)

in ()

5 return self.__name

6 p = Person()

----> 7 print(p.name)

AttributeError: 'Person' object has no attribute 'name'

print(p.getName())

小甲鱼

# 其实 Python 的私有为伪私有,只是将变量的名字改了(名字改编)

# 可以通过 对象名._类名__变量名 来调用

print(p._Person__name)

小甲鱼

6. 继承

class Parent:

def hello(self):

print("正在调用父类的方法。。。")

class Child(Parent):

pass

p = Parent()

p.hello()

c = Child()

c.hello()

正在调用父类的方法。。。

正在调用父类的方法。。。

class Child1(Parent):

# 如果在子类中定义与父类同名的方法或属性,则会覆盖父类相应的方法或属性

def hello(self):

print("正在调用子类的方法。。。")

d = Child1()

d.hello()

p.hello()

正在调用子类的方法。。。

正在调用父类的方法。。。

7. 继承例子

import random as r

class 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):

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("太撑了,吃不下了!")

fish = Fish()

fish.move()

我现在的位置是: 3 6

fish.move()

我现在的位置是: 2 6

goldfish = Goldfish()

fish.move()

我现在的位置是: 1 6

shark = Shark()

shark.eat()

吃货的梦想就是天天有得吃

# 由于 Shark 子类重写了 __init__ 方法,属性 x 和 y,都不存在了,所以会报错

shark.move()

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

AttributeError Traceback (most recent call last)

in ()

----> 1 shark.move()

in move(self)

5 self.y = r.randint(0,10)

6 def move(self):

----> 7 self.x -= 1

8 print("我现在的位置是:", self.x, self.y)

9

AttributeError: 'Shark' object has no attribute 'x'

class Shark1(Fish):

def __init__(self):

# 这里调用未绑定的父类方法

# 这里的 self 是子类的对象,即将子类对象作为参数传入父类的构造方法

# 从而定义了属性 x 和 y

Fish.__init__(self)

self.hungry = True

def eat(self):

if self.hungry:

print("吃货的梦想就是天天有得吃")

self.hungry = False

else:

print("太撑了,吃不下了!")

shark1 = Shark1()

shark1.eat()

shark1.move()

吃货的梦想就是天天有得吃

我现在的位置是: 8 9

class Shark2(Fish):

def __init__(self):

# 也可以使用super

super().__init__()

self.hungry = True

def eat(self):

if self.hungry:

print("吃货的梦想就是天天有得吃")

self.hungry = False

else:

print("太撑了,吃不下了!")

shark2 = Shark2()

shark2.eat()

shark2.move()

吃货的梦想就是天天有得吃

我现在的位置是: 5 9

8. 多重继承

# 尽量避免使用多重继承

class Base1:

def foo1(self):

print("我是foo1,我为Base1代言。。。")

class Base2:

def foo2(self):

print("我是foo2,我为Base2代言。。。")

class C(Base1, Base2):

pass

c = C()

c.foo1()

c.foo2()

我是foo1,我为Base1代言。。。

我是foo2,我为Base2代言。。。

9. 组合

class Turtles:

def __init__(self, x):

self.num = x

class Fishs:

def __init__(self, x):

self.num = x

class Pool:

def __init__(self, x, y):

# 把类的实例化放到一个新类中,这样就可以避免使用多重继承

self.turtles = Turtles(x)

self.fishs = Fishs(y)

def print_num(self):

print("水池里总共有乌龟 %d 只,小鱼 %d 条!" % (self.turtles.num, self.fishs.num))

pool = Pool(1,10)

pool.print_num()

水池里总共有乌龟 1 只,小鱼 10 条!

10. Mix-in 编程机制

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

# 在定义的时候他是一个类,等他定义完就是一个类对象

class C:

count = 0

a = C()

b = C()

c = C()

print(a.count)

print(b.count)

print(c.count)

0

0

0

# 这里相当于生成了一个对象来覆盖了原来的count

# 类中定义的属性都是静态属性

# 类属性和类对象是相互绑定的,并不依赖于实例对象

# 当执行 c.count += 10 的时候,c实例对象里面多出了一个count属性

# 这个实例属性将类属性给覆盖了

c.count += 10

print(c.count)

print(a.count)

print(b.count)

10

0

0

C.count += 100

print(a.count)

print(b.count)

print(c.count)

100

100

10

12. 属性和方法同名

class D:

def x(self):

print("X-man!")

d = D()

d.x()

X-man!

# 这里是在实例对象里创建一个新的变量x,与方法同名,会覆盖方法

d.x = 1

print(d.x)

1

d.x()

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

TypeError Traceback (most recent call last)

in ()

----> 1 d.x()

TypeError: 'int' object is not callable

不要试图在一个类里边定义出所有能想到的特性和方法,应该利用继承和组合机制来进行扩展。

用不同的词性命名,如属性名用名词,方法名用动词。

13. 绑定

Python要求方法需要有实例才能被调用,即为绑定

class BB:

# 这里没写参数 self

def printBB():

print("no zuo no die")

# 直接用类名可以调用

BB.printBB()

no zuo no die

# 由于没有 self 参数,所以实例化对象没办法调用该方法

bb = BB()

bb.printBB()

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

TypeError Traceback (most recent call last)

in ()

1 bb = BB()

----> 2 bb.printBB()

TypeError: printBB() takes 0 positional arguments but 1 was given

class CC:

# 方法是静态的,绑定在类对象中

def setXY(self, x, y):

self.x = x

self.y = y

def printXY(self):

print(self.x, self.y)

dd = CC()

# 以字典方式输出 dd 对象所有的属性

print(dd.__dict__)

# 只有实例对象的属性,不显示类属性和特殊属性(魔法方法)

# 键用引号引起来,表示属性名

# 值表明属性对应的值

print(CC.__dict__)

{}

{'__module__': '__main__', 'setXY': , 'printXY': , '__dict__': , '__weakref__': , '__doc__': None}

# 这里调用实际上调用的是dd.setXY(dd,4,5)

# x,y 变量储存在 dd 实例对象的空间中

dd.setXY(4,5)

# 这里的 x, y 仅属于dd

print(dd.__dict__)

print(CC.__dict__)

{'x': 4, 'y': 5}

{'__module__': '__main__', 'setXY': , 'printXY': , '__dict__': , '__weakref__': , '__doc__': None}

del CC

ee = CC()

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

NameError Traceback (most recent call last)

in ()

1 del CC

----> 2 ee = CC()

NameError: name 'CC' is not defined

# 虽然类对象已经被删除,但是实例对象已经储存在内存中,仍然可以使用

# 只有在程序退出时才会被释放

# 所以大多数情况下应该使用实例属性,而不要去使用类属性

dd.printXY()

4 5

14.一些BIF

① issubclass(class,classinfo)

如果 clss 是 classinfo 的子类,就会返回TRUE

一个类会被认为是其自身的子类

classinfo可以是类对象组成的元组,只要class是其中任何一个候选类的子类,则会返回True

class A:

pass

class B(A):

pass

class C:

pass

print(issubclass(B,A))

print(issubclass(B,B))

# 所有类都是object类的子类

print(issubclass(B,object))

print(issubclass(B,C))

True

True

True

False

② isinstance(object,classinfo)

如果 object 是 classinfo 的实例对象,就会返回TRUE

如果第一个参数不是对象,则永远返回False

classinfo可以是类对象组成的元组,只要object是其中任何一个候选类的实例对象,则会返回True

如果第二个参数不是类或者由类对象组成的元组,会抛出一个TypeError

b1 = B()

print(isinstance(b1,B))

# B类继承于A类

print(isinstance(b1,A))

print(isinstance(b1,C))

print(isinstance(b1,(A,B,C)))

True

True

False

True

③ hasattr(object,name)

测试object对象里面是否有属性name

class D:

def __init__(self,x=0):

self.x = x

d1 = D()

# 这里的属性名参数,必须加上引号,否则会报错

print(hasattr(d1,'x'))

True

④ getattr(object,name[,default])

返回对象指定的属性值,如果属性不存在,如果你还设置了default,则会打印出default;如果没设置,则会抛出AttributeError的异常

print(getattr(d1,'x'))

0

print(getattr(d1,'y'))

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

AttributeError Traceback (most recent call last)

in ()

----> 1 print(getattr(d1,'y'))

AttributeError: 'D' object has no attribute 'y'

print(getattr(d1,'y','您所访问的属性不存在'))

您所访问的属性不存在

⑤ setattr(object,name,value)

设置对象中指定属性的值,如果没有,则会新建并赋值

setattr(d1,'y','Nigream')

print(getattr(d1,'y'))

Nigream

⑥ delattr(object,name)

删除对象中指定的属性,如果不存在则抛出AttributeError的异常

delattr(d1,'y')

delattr(d1,'y')

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

AttributeError Traceback (most recent call last)

in ()

----> 1 delattr(d1,'y')

AttributeError: y

⑦ property(fget=None, fset=None, fdel=None, doc=None)

通过属性来设置属性

fget为获取属性的方法,当执行e1.x语句时调用

fset为设置属性的方法,当执行e1.x=18语句时调用

doc为删除属性的方法,当执行del e1.x语句时调用

class E:

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)

e1 = E()

print(e1.getSize())

10

print(e1.x)

10

e1.x = 18

print(e1.x)

18

print(e1.getSize())

18

del e1.x

e1.size

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

AttributeError Traceback (most recent call last)

in ()

----> 1 e1.size

AttributeError: 'E' object has no attribute 'size'

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值