python 人生苦短,我学Python(五)

1. 对象(Object)

理解好对象和实例关系。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 类(class)

在这里插入图片描述

定义类:

class MyClass():
	pass

# print(MyClass);
mc = MyClass(); # mc就是通过MyClass创建的对象,mc是MyClass的实例。
print(mc); # <__main__.MyClass object at 0x0000014E41FD4B20>

在这里插入图片描述

isinstance()用来检查一个对象是否是一个类的实例。

class MyClass():
	pass

# print(MyClass);

mc = MyClass(); # mc就是通过MyClass创建的对象,mc是MyClass的实例。
result = isinstance(mc,MyClass); # 检查mc是否时MyClass的实例
print(result); # True

3. 对象的创建流程

在这里插入图片描述

添加属性:
语法:对象.属性名 = 属性值;

class MyClass():
	pass

# print(MyClass);
mc = MyClass(); 
mc.name = '张三'; # 创建一个name属性。
print(mc.name);

方法调用:
在类中定义函数,类中的定义的函数,我们称为方法。调用方法也就是上面的方法调用。

方法调用语法:对象.方法名()

class Person():
	a = 10;
	b = 20;
	# 每一个方法必须定义一个形参,因为方法调用是,默认传递一个参数。
	def say_hello(a):
		print(a);
		print('你好,张三');

p1 = Person();
p2 = Person();
print(p1.a,p1.b);
print(p2.a,p2.b);
p1.say_hello();
p2.say_hello();

方法调用和函数调用的区别:
如果是函数调用,则调用时传入几个参数,就会有几个实参。
但是如果时方法调用,默认传递一个参数,所以方法中至少要定义一个形参。

4. 属性和方法查找的流程

1.当我们调用一个对象的属性时,解析器会先在当前对象中寻找是否函数该属性。
2.如果有,则直接返回当前对象的属性值。
3.如果没有,则去当前对象的类对象中去寻找,如果有则返回类对象的属性值,如果没有则报错。

在这里插入图片描述
总结:
在这里插入图片描述

类方法传递的第一个参数self:

其实,self就是实例对象

class Person():
	name = '默认名字';
	def say_hello(self):
		# 方法每次调用时,解析器都会自动传递第一个实参。
		# 通过打印知道,这里的self就是实例对象p1或p2,看谁调用。
		# 一般我们都将这个参数命名为self。
		print(self); 
		print('你好,%s'%self.name);

p1 = Person();
p2 = Person();

p1.name = '张三';
p2.name = '李四';

print(p1);
p1.say_hello();

print(p2);
p2.say_hello();
# 通过打印知道,这里的p1或p2和上面的self是一样的实例对象,看谁调用。


# <__main__.Person object at 0x0000029CFDD84B20>
# <__main__.Person object at 0x0000029CFDD84B20>
# 你好,张三
# <__main__.Person object at 0x0000029CFDDB7FD0>
# <__main__.Person object at 0x0000029CFDDB7FD0>
# 你好,李四

5. 类的特殊方法 init

  • 在类中,可以定义写特殊方法(也叫魔术方法)。
  • 特殊方法都是以__(双下划线)开头,__(双下划线)结尾的。 例如:__init__ 。
  • 特殊方法不需要我们来调用,像__init__不要去调用!!。
  • 特殊方法将会在特殊时刻自动调用。

创建对象的流程

1.创建一个变量。
2.在内存中创建一个新对象。
3.执行类的代码块中中的代码(只在类定义的时候执行一次)。
4._init_(self)方法执行…
5.将对象的id赋值给变量。

class Person():

	print('执行代码块中的代码1');

	def __init__(self):
		print('__init__已经执行了');

	print('执行代码块中的代码2');

	def say_hello(self,a):
		print(self); 
		print(a);
		print('你好,%s'%self.name);

p1 = Person();
# 执行代码块中的代码1
# 执行代码块中的代码2
# __init__已经执行了
  • init会在对象创建以后立刻执行。
  • init可以用来向新创建的对象中初始化属性。
class Person():

	# name = '张三'; # 这个是在person类里面创建的name属性。
	def __init__(self):
		print(self);
		self.name = '张三'; # 而这个self.name是在实例对象中创建的属性。
	

	def say_hello(self,a):
		print(self); 
		print(a);
		print('你好,%s'%self.name);

p1 = Person();

p2 = Person();

print(p1.name);
print(p2.name);
# <__main__.Person object at 0x000001AE015C4B20>
# <__main__.Person object at 0x000001AE016070A0>
# 张三
# 张三

__init__参数,定义了几个,创建对象时必须传递几个,有一个是默认的self。

class Person():
	
	# 调用类创建对象时,类后边的所有参数都会一次传递到init()中。
	def __init__(self,name): 

		self.name = name;

	def say_hello(self,a):
		print(self); 
		print(a);
		print('你好,%s'%self.name);

p1 = Person('张三');
p2 = Person('李四');

print(p1.name);
print(p2.name);

# 因为上面__init__需要name参数,因此,在创建p1时,我们必须传递一个name参数,否则报错。

# 张三
# 李四

类的基本结构,如下:
在这里插入图片描述

对象.属性 的方式来修改属性的值,不好!非常不安全。

在这里插入图片描述

6. 封装

  • 封装指的是隐藏对象中一些不希望被外部所访问到的属性和方法。

如何获取(修改)对象中的属性?

  • 需要提供一个getter和setter方法使外部可以访问到属性。
  • getter 获取对象中的指定属性(get_属性名)。
  • setter 用来设置对象的指定的属性(set_属性名)。
class Dog:
	def __init__(self,name):
		self.hidden_name = name;

	def say_hello(self):
		print('大家好,我是%s'%self.hidden_name);

	def get_name(self):
		# print('用户读取了属性');
		return self.hidden_name;

	def set_name(self,New_name):
		# print('用户修改了属性');
		self.hidden_name = New_name;

d = Dog('二哈');

d.say_hello();
print(d.get_name()); # 通过getter来查看属性值

d.set_name('金毛'); # 通过setter来改变属性值

print(d.get_name());

# 大家好,我是二哈
# 二哈
# 金毛

注意:向hidden_name这种只是改了一个名字,和使用__双下划线来操作隐藏属性是一样的都是通过改名字来操作的。

getter和setter的优缺点:
在这里插入图片描述
可以为对象的属性使用双下划线开头,__xxx,这是对象的隐藏属性。

  • 隐藏属性只能在类的内部访问,无法通过对象访问。
  • 其实隐藏属性只不过是Python自动为属性改了一个名字,实际上是将名字修改为了,_类名__属性名。例如:__name -> _Person__name。
class Person:
	def __init__(self,name):
		self.__name = name;

	def get_name(self):
		return self.__name;

	def set_name(self,New_name):
		self.__name = New_name;

p = Person('张三');

print(p.get_name());

p.set_name('李四');

print(p.get_name());

# print(p.__name); # __双下划线开头的属性是隐藏属性,无法通过对象访问。
print(p._Person__name); # 也是改名字。将名字修改为了,_类名__属性名。例如:__name -> _Person__name。

像上面改名字使用__双下划线操作的方式,我们一般不用。一般我们会将一些私有属性(不希望被外部访问的属性)以_(单下划线)开头。

  • _(单下划线)开头依然还是可以修改了属性的,它的目的就是告诉我们不建议修改。

7. @property装饰器 和 @属性名.setter装饰器

其实,@property装饰器 和 @属性名.setter装饰器,就是像属性调用一样来操作,实际上还是方法调用。

  • property装饰器,用来将一个的get方法,转换为对象的属性。
  • 添加property装饰器以后,我们就可以调用属性一样来调用get方法。
  • 注意使用property装饰的方法,必须和属性名一样的。
  • setter方法的装饰器:@属性名.setter ,setter装饰器必须和property装饰器的get配合使用。
class Person:
	def __init__(self,name):
		self._name = name;

	@property # property装饰器,用来将一个的get方法,转换为对象的属性。
	# 添加property装饰器以后,我们就可以调用属性一样来调用get方法。
	# 注意使用property装饰的方法,必须和属性名一样的。
	def name(self):
		print('get方法执行了~~');
		return self._name;

	# setter方法的装饰器:@属性名.setter
	@name.setter	
	def name(self,name):
		print('setter方法执行了~~');
		self._name = name;


p = Person('张三');

print(p.name); # 不是p.name()这样调用,而是像调用属性一样。

p.name = '李四';

print(p.name);

8. 继承

继承就是对一个类进行扩展。
在这里插入图片描述

格式:

class 类名([父类]):

  • 父类又叫超类,基类,super。
  • 子类(衍生类)可以直接继承父类中的所有的属性和方法。
class Animal:
	def run(self):
		print('动物会跑~~');

	def sleep(self):
		print('动物睡觉~~');

	def bark(self):
		print('动物嚎叫~~');

# 父类又叫超类,基类,super。
# 子类(衍生类)可以直接继承父类中的所有的属性和方法。
class Dog(Animal):
	def bark(self):
		print('汪汪汪~~');

class Hashiqi(Dog): # 同样该继承也是可以调用Dog和Animal的方法。
	def fangsha(self):
		print('我是一只傻傻的哈士奇');

d = Dog();

d.run();
d.sleep();
d.bark();

# 检查一个对象,是否是类的实例
result1 = isinstance(d,Dog);
result2 = isinstance(d,Animal);
print(result1,result2); # 返回的都是True,也就是说d对象既是Dog,也是Animal。
  • 在创建时,如果省略了父类,则默认父类为object。
  • object是所有类的父类,所有类都继承自object。
  • issubclass(a,b) # 判断a是否为b的子类,是返回True,否返回False。
  • isinstance()用来检查一个对象是否是一个类的实例。
  • 注意:所有的对象都是object的实例!
# Person不加括号,也是默认继承的object,可以通过issubclass()来判断验证。
class Person(object):
	pass

print(issubclass(Person,object));
print(isinstance(print,object));
# True
# True

9. 方法重写(覆盖,override)

在这里插入图片描述
在这里插入图片描述

10. super

  • 父类中的所有方法都会被子类继承,包括特殊方法__init__ 。
  • 对于特殊方法,也是可以在子类中重写的。
  • super() 可以用来获取当前类的父类,并且通过super() 返回对象调用父类方法时,不需要传递self。
  • 通过super()返回对象调用父类方法时,不需要传递self。
class Animal:
	def __init__(self,name):
		self._name = name;

	def run(self):
		print('动物会跑~~');

	def sleep(self):
		print('动物睡觉~~');

	@property
	def name(self):
		return self._name
	
	@name.setter
	def name(self,name):
		self._name = name;

class Dog(Animal):

	def __init__(self,name,age):
		# 通过super()返回对象调用父类方法时,不需要传递self。
		super().__init__(name);
		self._age = age;

	def bark(self):
		print('汪汪汪~~');
	def run(self):
		print('狗跑~~');

	@property
	def age(self):
		return self._age
	
	@age.setter
	def age(self,age):
		self._age = age;

d = Dog('二哈',18);

print(d.name,d.age);

d.name = '金毛';
d.age = 22;

print(d.name,d.age);

11. 多重继承

先记住一个隐藏属性:

  • __bases__ ,bases 这个隐藏属性可以用来获取当前类的所有父类。
    在这里插入图片描述

注意:开发中没有特殊情况,应该尽量避免使用多重继承,因为多重继承会让我们的代码过于复杂。

12. 多态

面向对象三大特征:封装,继承,多态。
在这里插入图片描述
__len__ ,len方法的隐藏属性:
在这里插入图片描述

class B:
	def __init__(self,name):
		self._name = name

	# 定义了len,这样就可以调用len()方法来操作了
	def __len__(self):
		return 10;

	@property
	def name(self):
		return self._name
	@name.setter
	def name(self,name):
		self._name = name;
		
b = B('李四');
print(len(b)); # 10

在这里插入图片描述

13. 类中的属性和方法

理解好这几个名词:类属性,实例属性,实例方法,类方法。

类属性:在这里插入图片描述
实例属性:
在这里插入图片描述
实例方法:
在这里插入图片描述
类方法 @classmethod :

  • 类方法的第一个参数是cls,也会被自动传递,cls就是当前的类对象。
  • 类方法和实例方法区别,实例方法第一个参数self,类方法第一个参数是cls(当前类对象),其他都差不多。

静态方法 @staticmethod :

  • 在类中使用 @staticmethod 来修饰的方法属于静态方法。
  • 静态方法不需要指定任何的默认参数,静态方法可以通过类和实例去调用。
  • 静态方法,基本上是一个和当前类无关的方法,它只是一个保存到当前类中的函数。
  • 因此静态方法一般都是一些工具方法,和当前类无关。
class A(object):

	# 类属性
	count = 0

	def __init__(self):
		# 实例属性
		self.name = '张三'

	# 实例方法
	def test(self):
		print('这是个test方法~~',self)

	# 类方法 @classmethod
	# 类方法的第一个参数是cls,也会被自动传递,cls就是当前的类对象。
	# 类方法和实例方法区别,实例方法第一个参数self,类方法第一个参数是cls(当前类对象)
	# 类方法可以通过类和实例去调用。
	@classmethod
	def test_2(cls):
		print('这是test_2方法~~,这是一个类方法',cls);


	# 静态方法
	# 在类中使用 @staticmethod 来修饰的方法属于静态方法。
	# 静态方法不需要指定任何的默认参数,静态方法可以通过类和实例去调用。
	# 静态方法,基本上是一个和当前类无关的方法,它只是一个保存到当前类中的函数。
	# 因此静态方法一般都是一些工具方法,和当前类无关。
	@staticmethod
	def test_3():
		print('test_3执行了~~');
a = A();

A.test_2(); # 通过类去调用
a.test_2(); # 通过实例调用

14. 垃圾回收

  • 程序在运行过程中也会产生垃圾。
  • 程序运行过程中产生的垃圾会影响到程序的运行性能,所以这些垃圾必须被及时清理。
  • 什么是垃圾?在程序中没有被引用的对象就是垃圾。

在这里插入图片描述

  • 格式:def __del__(self): 函数来调用垃圾回收
class A:
	def __init__(self):
		self.name = 'A类'

	# del是一个特殊方法,它会在对象被垃圾回收前调用。
	def __del__(self):
		print('A()对象被删除了~~',self)


a = A();
b = a;  # 如果有b为a,那么b也是一个A()对象,也是调用A的,就算a设置为了None,b依然还是指向A对象的。
# print(id(b),id(a),id(A()));

a = None # 这个时候将a设置为None,此时没有任何的变量对A()对象进行引用,它就变成了垃圾。

# del a;
# del b;

input('回车键退出'); # input回车后,程序也会自动删除,调用垃圾回收

15. 特殊方法(魔术方法)

特殊方法(魔术方法),以__开头结尾的。
在这里插入图片描述
__str__(self): 特殊方法

  • 功能:当我们打印一个对象时,实际上打印的时对象中的特殊方法__str__()的返回值。

  • 这个特殊方法会在尝试将对象转换为字符串的时候调用。

  • 它的作用可以用来指定对象转换为字符串的结果。

class Person(object):

	def __init__(self,name,age):
		self._name = name;
		self._age = age;

	def __str__(self):
		return 'Person [name=%s,age=%d]'%(self._name,self._age);

p1 = Person('张三',18);
p2 = Person('王五',24);

# 当我们打印一个对象时,实际上打印的时对象中的特殊方法__str__()的返回值。
print(p1)
print(p2)
# Person [name=张三,age=18]
# Person [name=王五,age=24]

__repr__(): 特殊方法

  • __repr__():这个特殊方法会对当前对象使用repr()函数时调用。
  • 作用:指定对象在 交互模式 中直接输出的效果。
class Person(object):

	def __init__(self,name,age):
		self._name = name;
		self._age = age;

	def __str__(self):
		return 'Person [name=%s,age=%d]'%(self._name,self._age);

	# __repr__这个特殊方法会对当前对象使用repr()函数时调用。
	# 作用:指定对象在 `交互模式` 中直接输出的效果。
	def __repr__(self):
		return 'hello';


p1 = Person('张三',18);
p2 = Person('王五',24);

print(repr(p1));
print(repr(p2));

在这里插入图片描述
大于小于 … (比较运算符)的特殊方法:
在这里插入图片描述
其中:
上面的self表示当前对象,other表示和当前对象比较的对象。

class Person(object):

	def __init__(self,name,age):
		self._name = name;
		self._age = age;

	def __str__(self):
		return 'Person [name=%s,age=%d]'%(self._name,self._age);

	def __repr__(self):
		return 'hello';

	# __gt__会在对象做大于比较的时候调用,该方法的返回值将会作为比较的结果
	# self表示当前对象(就像下面的p1),other表示和当前对象比较的对象(就像下面的p2)。
	def __gt__(self,other):
		return self._age > other._age;

	# 其他的lt,le,eq等等,都是一样的

p1 = Person('张三',18);
p2 = Person('王五',24);

print(p1 > p2);

__len__(): 获取对象长度len的特殊方法。

就像之前操作一样。

__bool__(): 特殊方法

  • __bool__(): 特殊方法,作用:通过bool来指定对象转换为布尔值的情况。
class Person(object):

	def __init__(self,name,age):
		self._name = name;
		self._age = age;

	def __str__(self):
		return 'Person [name=%s,age=%d]'%(self._name,self._age);

	def __repr__(self):
		return 'hello';

	def __gt__(self,other):
		return self._age > other._age;

	# __bool__特殊方法,作用:通过bool来指定对象转换为布尔值的情况。
	def __bool__(self):
		return self._age > 17;

p1 = Person('张三',18);
p2 = Person('王五',24);

print(bool(p1));

运算的特殊方法:

  • 各种各样,加法减法,或与等等很多,都需要了解!
    在这里插入图片描述
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

xupengboo

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

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

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

打赏作者

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

抵扣说明:

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

余额充值