Python3 基础学习笔记5-类和对象

目录

一、基础知识

1.面向对象编程和面向过程编程的区别?

2.一个类通常都定义了什么?

3.函数与类的区别

二、公有和私有

1.默认对象的属性和方法都是公有的

2.定义私有变量只需在变量名或函数名前加上”__“双下划线

三、继承

1.子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性

2.子类继承父类时,子类若重写魔法方法,则应在子类重写魔法方法的时候先调用父类的魔法方法

3.多重继承

4.组合和绑定

5.一些相关的BIF

一、基础知识

1.面向对象编程和面向过程编程的区别?

# 一、面向过程

>>> fruit1 = {'name' : 'Apple', 'sweetness' : 'C'}
>>> fruit2 = {'name' : 'Banana', 'sweetness' : 'B'}
>>> def print_fruit(fruit1):
        print('水果名称:%s\n甜度:%s' % (fruit1['name'], fruit1['sweetness']))
>>> print_fruit(fruit1)


#二、面向对象
>>> class Fruit:
...     def __init__(self, name, sweetness):
...         self.name = name
...         self.sweetness = sweetness
...     def print_fruit(self):
...         print('水果名称:%s\n甜度:%s' % (self.name, self.sweetness))
>>> fru = Fruit('Apple','C')
>>> fru.print_fruit()

水果名称:Apple
甜度:C

2.一个类通常都定义了什么?

对象的特征(即属性)和行为(即方法)

3.函数与类的区别

类名约定用大写字母开头,函数用小写字母开头

二、公有和私有

1.默认对象的属性和方法都是公有的

>>> class Person:
...     name  = "666"
>>> p = Person()
>>> p.name
'666'

2.定义私有变量只需在变量名或函数名前加上”__“双下划线

Python 采用 Name Mangling(名字改编技术),这样若要访问私有变量则从理论上讲要从内部进行

>>> class Person:
...     def __init__(self,name):
...         self.__name = name
...     def getname(self):
...         return self.__name
>>> p = Person("666")
>>> p.getname()
'666'

# 外部调用则报错
>>> p.__name
AttributeError

三、继承

1.子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性

>>> class Parent:
...     def inherit(self):
...         print("正在调用父类的方法")
>>> class Child(Parent):
...     def inherit(self):
...         print("正在调用子类的方法")
>>> c = Child()
>>> c.inherit()
'正在调用子类的方法'

2.子类继承父类时,子类若重写魔法方法,则应在子类重写魔法方法的时候先调用父类的魔法方法

两种实现技术:(1)调用未绑定的父类方法;(2)使用super函数(其与父类没有直接关系,获取的是 MRO 列表中下一个类

(MRO详解参考:Python的MRO_鄙人张钊_有何贵干的博客-CSDN博客_mro python

# 采用”小甲鱼“书中的例子

# 方法一:调用未绑定的父类方法

>>> 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 Shark(Fish):
...     def __init__(self):
...         Fish.__init__(self)    # 方法二采用 super 函数:super().__init__()
...         self.hungry = True
...     def eat(self):
...         if self.hungry:
...             print("吃吃吃!")
...             self.hungry = False
...         else:
...             print("饱了!")

>>> shark = Shark()
>>> shark.eat()
'吃吃吃!'
>>> shark.eat()
'饱了!'
>>> shark.move()
# 若不添加 Fish.__init__(self) 或 super().__init__() 则报错
# 子类中重写魔法方法,但没有初始化Shark的坐标,所以调用 move() 方法会出错
# 因此需先调用基类的魔法方法

3.多重继承

(1)语法:class 类名(父类1,父类2,...)

(2)注意:不确定必须使用多重继承时就尽量不用,易出现钻石继承(菱形继承)等问题

(3)举例

>>> class A:
...     def goods1(self):
...         print("goods1在A中") 
>>> class B:
...     def goods2(self):
...         print("goods2在B中")
>>> class C(A, B):
...     pass

>>> ab = C()
>>> ab.goods1()
goods1在A中
>>> ab.goods2()
goods2在B中

4.组合和绑定

组合:将需要的类放在一起进行实例化

>>> class Apple:
...     def __init__(self, x):
...         self.level = x
>>> class Banana:
...     def __init__(self, y):
...         self.level = y
>>> class Fruits(Apple, Banana):
...     def __init__(self, x, y):
...         self.apple = Apple(x)
...         self.banana = Banana(y) 
...     def sweetness_level(self):
...         print("苹果的甜度等级为%s\n香蕉的甜度等级为%s" % (self.apple.level, self.banana.level))

>>> fruits = Fruits('C', 'B')
>>> fruits.sweetness()
苹果的甜度等级为C
香蕉的甜度等级为B

绑定:Python 严格要求方法需要有实例才能被调用

>>> class CC:
...     def setXY(self, x, y):
...         self.x = x
...         self.y = y
...     def printXY(self):
...         print(self.x, self.y)

>>> dd = CC()
>>> dd.__dict__
{}
>>> CC.__dict__
# 此处以字典显示实例对象的属性

>>> dd.setXY(2, 3)
>>> dd.__dict__
{'x': 2, 'y': 3}

# 删除类实例,而实例对象 dd 仍可调用类方法
>>> del CC
>>> dd.printXY()
2 3

5.一些相关的BIF

(1)issubclass(class, classinfo)

>>> class A:
...     pass
>>> class B(A):
...     pass

# 1.若首个参数(class)是第二个参数(classinfo)的一个子类,则返回 True ,否则返回 False
>>> issubclass(B,A)
True

# 2.一个类被认为是其自身的子类
>>> issubclass(B,B)
True

# 3.classinfo 可以是类对象组成的元组,只要 class 是其中一个候选类的子类,则返回True
>>> issubclass(B,object)  # object 是所有类的基类
True

>>> class C:
...     pass
>>> issubclass(B,C)
False

(2)isinstance(object, classinfo)

# 1.若首个参数(object)是第二个参数的实例对象(classinfo),则返回 True,否则返回 False
>>> issubclass(B,C)
False
>>> b1 = B()
>>> issubclass(b1,B)
True

# 2.若 object 是 classinfo 的子类的一个实例,也符合条件
>>> isinstance(b1,C)
False
>>> isinstance(b1,A)
True

# 3.classinfo 可以是类对象组成的元组,只要 object 是其中任何一个候选类的子类,则返回 True
>>> isinstance(b1,(A,B,C))
True

(3)hasattr(object, name):测试一个对象是否有指定的属性,attr 即 attribute 的缩写,属性的意思,object 是对象,name 是属性名

>>> class C:
...     def __init__(self, x = 0):
...         self.x = x

>>> c1 = C()
>>> hasattr(c1, 'x')    # 属性名要用引号括起来
True

(4)getattr(object, name[ ,default]):返回对象指定的属性值,若指定的属性不存在,则返回default(可选参数)的值,若未设 default 参数,则抛出 ArttributeError 异常

>>> class C:
...     def __init__(self, x = 0):
...         self.x = x

>>> c1 = C()
>>> getattr(c1, 'x')
0
>>> getattr(c1, 'y')
AttributeError
>>> getattr(c1, 'y', '您所访问的属性不存在...')
您所访问的属性不存在...

(5)setattr(object,name,value):设置对象中指定的属性值,若不存在,则新建属性并赋值

>>> setattr(c1, 'y', '666')
>>> getattr(c1, 'y')
'666'
>>> setattr(c1, 'y', 666)
>>> getattr(c1, 'y')
666

(6)delattr(object,name):用于删除对象中指定的属性,若属性不存在,抛出 AttributeError 异常

>>> delattr(c1, 'y')
>>> hasattr(c1, 'y')
False
>>> delattr(c1, 'z')
AttributeError

(7)property(fget = None, fset = None, fel = None, doc = None):通过属性设置属性

# 为用户访问只提供了 x 属性,无论内部如何改动,只需要相应地修改 property() 的参数,用户仍然只需要操作 x 的属性即可

>>> class C:
...     def __init__(self, size = 10):
...         self.size = size
...
...     def getSize(self):
...         return self.size
...
...     def setSize(self):
...         self.size = value
...
...     def delSize(self):
...         del self.size
...     
...     x = property(getSize, setSize, delSize)
>>> c = C()
>>> c.x
10
>>> c.x = 12    # 不能对c.x赋值的原因?
TypeError: setSize() takes 1 positional argument but 2 were given

>>> c.size = 12   
>>> c.x
12
>>> del c.x
>>> c.size
AttributeError: 'C' object has no attribute 'size'

# 将 property 函数用作装饰器可以很方便的创建只读属性
>>> class PropTest(object):
...     def __init__(self):
...         self._number = 1234
...     # 将 number_getter() 方法转化成同名只读属性的 getter 方法
...     @property
...     def number_getter(self):
...         return self._number
>>> a = PropTest()
>>> a._number
1234

你可能感兴趣的:(Python,python)