【面向对象编程】Note by Liao

面向对象编程

https://www.liaoxuefeng.com/

1. 类和实例

class Student(object):
	def __init__(self, name):
		self.name = name

类是创建实例的模板,而实例则是一个一个具体的对象,各个实例互相独立,互不影响。

  • object 表示该类从哪个类继承下来的。所有类都从 object 继承下来。
  • __init__ 类似构造函数。

2. 访问限制

class Student(object):
	def __init__(self, name, score):
		self.__name = name
		self._score = score
	
	def get_name(self):
		return self.__name
  • __name 双下划线开头,私有变量(只能内部访问,不能外部访问);
    • P s 1 \color{blue}{{Ps}_1} Ps1 可以通过 any_instance_name._Student__name 进行外部访问,但不建议这么干!
    • P s 2 \color{blue}{Ps_2} Ps2 不要在外部,通过 any_instance_name.__name = "Some Value" 对私有变量进行赋值。
      • 这样看起来没错,实际上多创建了一个变量,很容易出问题的。
  • _score 单下划线开头,保护成员(可以外部访问,但当作私有变量);
  • 私有成员保护成员 的作用是为了更好地封装起来(个人理解)。

3. 继承和多态

3.1 继承

class Animal(object):
	def run(self):
		print("Animal is running...")

class Dog(Animal):
	pass

class Cat(Animal):
	pass
  • 子类 DogCat 继承了 父类 Animal 的全部功能。

3.2 多态

class Animal(object):
	def run(self):
		print("Animal is running...")

class Dog(Animal):
	def run(self):
		print("Animal is running...")

class Cat(Animal):
	def run(self):
		print("Animal is running...")
  • 子类 存在和 父类 相同的方法,此时,子类的方法覆盖 父类的方法

4. 获取对象信息

4.1 type()

  • 判断基本类型都可以用 type()
  • 判断一个变量是否指向 函数 或者
    • >>> type(abs)
    • <class 'builtin_function_or_method'>

4.2 isinstance()

  • 判断一个对象是否是 该类型本身,或者位于 该类型的父继承类链上。
  • a = Animal()
  • isinstance(a, Animal) -> True
  • isinstance(123, int) -> True
  • 总是优先使用 isinstance() 判断类型,因为它能将指定类型及其子类“一网打尽”。

4.3 dir()

  • 如果要获得一个对象的所有属性和方法,可以使用 dir() 方法。
>>> dir("ABC")
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
  • 由上面这个例子,可以说明 Python一切皆是对象
  • 所以 len('ABC') 等 价 \color{blue}{等价} 'ABC'.__len__(),都为 3,由此展开到 4.4 讲一点其他东西。
    • 实际上,在调用 len() 函数时,它自动调用该对象的 __len__() 方法。

4.4 其他说明

  • 类似 __xxx__属性或者方法 在 Python 中都是有特殊用途的。
  • 可以在类里面加(例子见下)。
class MyObject(Object):
	def __init__(self):
		self.x = 9
	def __len__(self):
		return 100
test = MyObject()
print(len(test)) # 100

4.5 getattr(), setattr(), hasattr()

  • 直接对一个对象的属性和方法进行操作。
>>> class MyObject(object):
...     def __init__(self):
...         self.x = 9
...     def power(self):
...         return self.x * self.x
...
>>> obj = MyObject()

>>> hasattr(obj, 'x') # 有属性'x'吗?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有属性'y'吗?
False
>>> setattr(obj, 'y', 19) # 设置一个属性'y'
>>> hasattr(obj, 'y') # 有属性'y'吗?
True
>>> getattr(obj, 'y') # 获取属性'y'
19
>>> obj.y # 获取属性'y'
19

>>> getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404
404

>>> hasattr(obj, 'power') # 有属性'power'吗?
True
>>> getattr(obj, 'power') # 获取属性'power'
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn
>>> fn # fn指向obj.power
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn() # 调用fn()与调用obj.power()是一样的
81

5. 实例属性和类属性

5.1 实例属性

  • 给实例绑定属性:通过实例变量,或者通过 self 变量。
class Student(object):
    def __init__(self, name):
        self.name = name

s = Student('Bob')
s.score = 90

5.2 类属性

  • 给类本身绑定一个属性:可以直接在class中定义属性。
class Student(object):
    name = 'Student'
  • 例子:当我们定义了一个类属性后,这个属性虽然归类所有,但类的所有实例都可以访问到。
  • 关于【类属性】
>>> class Student(object):
...     name = 'Student'
...
>>> s = Student() # 创建实例s
>>> print(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性
Student
>>> print(Student.name) # 打印类的name属性
Student
  • 关于【实例属性】
>>> s.name = 'Michael' # 给实例绑定name属性
>>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
Michael
>>> print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问
Student
>>> del s.name # 如果删除实例的name属性
>>> print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了
Student

5.3 小测试

  • 为了统计学生人数,可以给Student类增加一个类属性,每创建一个实例,该属性自动增加。
class Student(object):
    count = 0

    def __init__(self, name):
        self.name = name
        Student.count += 1
        
# 测试:
if Student.count != 0:
    print('测试失败!')
else:
    bart = Student('Bart')
    if Student.count != 1:
        print('测试失败!')
    else:
        lisa = Student('Bart')
        if Student.count != 2:
            print('测试失败!')
        else:
            print('Students:', Student.count)
            print('测试通过!')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

panzhong171

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值