类的创建和init方法

  • Post author:
  • Post category:其他


assert+条件,断言,用于强制用户服从,不服从就报错,可捕获,一般不捕获

assert 1==2

报错


一、两大编程思想

1.面向过程 事物比较简单,可以用线性思维去解决

2.面向对象 事物比较复杂,不可以用线性思维去解决

面向对象,便于从宏观上把握事物之间的联系,而具体到微观层面,依然使用面向过程处理。


二、类和对象创建

1.类:类是多个类似事物组成群体的统称。可帮助快速理解和判断事物的性质

2.类之下包含的相似的不同的个例 python中一切皆对象

# 默认继承object类
class bar:
	# 类属性 类中方法外的属性 被该类所有方法共享
	barda = 'barda'
	# 初始化构造方法
	def __init__(self,name,age):
		self.name = name # 实例属性
		self.__age = age # __表示私有属性
	# 实例方法
	def foo(self):
		print(self.name,self.__age)
	# 静态方法 不写self
	@staticmethod
	def method():
		print('我是静态方法')
	# 类方法 写cls
	@classmethod
	def classmeth(cls):
		print('我是类方法')

# 对象创建 类的实例化
z=bar('zhao',21)  # 创建时自动调用_init_方法
# print(id(z)) # 实例对象的内存地址 16进制 print(type(z)) # 类型 <class '__main__.bar'> print(z)
# print(id(bar)) # 类对象的内存地址 16进制 print(type(bar)) # 类型 <class 'type'> print(bar)

# 调用foo方法
z.foo()
bar.foo(z)
# 调用实例属性
print(z.name)
# 私有属性外部不可直接访问
# print(z.__age)
# 但是可以通过_类名__属性访问
print(z._bar__age)
# 类属性的调用
print(bar.barda)
print(z.barda)
# 类属性的修改
bar.barda='barda1'
print(z.barda)
# 类方法使用
bar.classmeth()
z.classmeth()
# 静态方法
bar.method()
z.method()
# 为z动态添加gender属性
z.gender = '女'
print(z.gender)
# 为z动态添加函数
def hello():
	print('hello word')
z.hello = hello
z.hello()

# object类的方法
print(z.__dict__)  # 将内容通过字典的形式返回 属性字典
# {'n': 'zhao', 'a': 21}
print(bar.__dict__)  # 将对象中封装的所有内容通过字典的形式返回 方法字典
# {'__module__': '__main__', 'barda': 'barda1', '__init__': <function bar.__init__ at 0x0000021141E36EE8>, 'foo': <function bar.foo at 0x0000021141E3D558>, 'method': <staticmethod object at 0x0000021148E08A48>, 'classmeth': <classmethod object at 0x0000021148E08A88>, '__dict__': <attribute '__dict__' of 'bar' objects>, '__weakref__': <attribute '__weakref__' of 'bar' objects>, '__doc__': None}
class Foo:
	stat = '999'
	def __init__(self, name, age):
		self.name = name
		self.age = age
	def show(self):
		return  "%s-%s" %(self.name,self.age)
	def __int__(self):
		return 123
	# 重写object的str方法 返回对象描述
	def __str__(self):
		return self.name

obj = Foo('zz', 18)
# 取属性
print(obj.__dict__['name'])
print(getattr(obj,'name'))
print(getattr(Foo, 'stat'))
# 取方法
print(getattr(obj,'show')())
# str(obj)走__str__方法
u1 = str(obj) # zz
# int(obj)走__int__方法
u = int(obj) # 123
# 通过字符串的形式操作对象中的成员
print(hasattr(obj, 'show'))  # 判断对象是否存在方法或属性
setattr(obj, 'k1', 'v1')  # 添加字典的键k1和值v1
delattr(obj, 'name')  # 删除属性
print(obj.__dict__) # {'age': 18, 'k1': 'v1'}


三、封装继承多态

封装:提高程序安全性,将数据和方法包装到类中

继承:复用性

多态:可扩展性和可维护性


类的继承 多继承

class Person(object):  # 定义一个父类
	def talk(self):  # 父类中的方法
		print("person is talking....")

class Chinese(Person):  # 定义一个子类, 继承Person类
	def walk(self):  # 在子类中定义其自身的方法
		print('Chinese is walking...')

c = Chinese( )
c.talk( )  # 调用继承的Person类的方法 person is talking....
c.walk( )  # 调用本身的方法 Chinese is walking...

class A(object):
	pass
class B(object):
	pass	
class C(A,B):
	pass


代码复用

class Tearch:
    def __init__(self, name,age):
        self.name = name
        self.age = age
        self.salary = 1000

class Course:
    def __init__(self, name, cost, tearcher):
        self.name = name
        self.tearcher = tearcher
        self.cost = cost

    def class_up(self):
        self.tearcher.salary += self.cost

t1 = Tearch('李杰' ,8)
t2 = Tearch('烧饼', 9)
c1 = Course('生理课', 1, t1)
print(c1.tearcher.salary) # 1000
c1.class_up()
print(c1.tearcher.salary) # 1001


class F1:
    def __init__(self):
        self.name = 123
class F2:
    def __init__(self, a):
        self.ff = a
class F3:
    def __init__(self, b):
        self.dd = b

f1 = F1()  # [name=123]
print(f1.name)
f2 = F2(f1)  # [ff=[name=123]]
print(f2.ff.name)
f3 = F3(f2)  # [dd=[ff=[name=123]]]
print(f3.dd.ff.name)


子类对父类方法的重写

# 父类
class Person(object):
	def __init__(self, name, age):
		self.name = name
		self.age = age
		self.weight = 'weight'
	def talk(self):
		print("person is talking....")
# 子类
class Chinese(Person):
	def __init__(self, name, age, language):
		# super().__init__(name, age)
		super(Chinese, self).__init__(name, age)
		# Person.__init__(self, name, age) # 继承父类的构造方法,也可以写成:super().__init__(name, age)
		self.language = language # 定义类的本身属性
		print(self.name, self.age, self.weight, self.language)
	def talk(self):  # 子类 方法重写
		print('%s is speaking chinese' % self.name)
	def walk(self):
		print('%s is walking...' % self.name)

c = Chinese('zz', 15, 'Chinese') # zz 15 weight Chinese
c.talk( ) # zz is speaking chinese


四、特殊属性和方法

__dir__字典结构

__class__输出对象所属的类

__bases__父类的类别

__mro__类的层次结构方法

class Foo:
	def f1(self):
		return 123
	def f2(self, v):
		print(v)
	def f3(self):
		print('del')
	per = property(fget=f1, fset=f2, fdel=f3)

obj = Foo()
# 取数据 走fget
ret = obj.per
print(ret)  # 得到的值为f1函数执行的 返回123
# 设置数据 走fset
obj.per = 123456  # 设置值的为f2,输出传入的值
# 删除数据 走fdel
del obj.per  # 删除时执行f3,打印del
class Foo:
	def __init__(self, name,age):
		self.name = name
		self.age = age

	def __getitem__(self, item):
		# 如果item是基本类型:int,str,索引获取
		# 若为slice对象的话,切片
		if type(item) == slice:
			print('调用者希望内部做切片处理')
		else:
			print(item.start)
			print(item.stop)
			print(item.step)
			print('调用者希望内部做索引处理')

	def __setitem__(self, key, value):
		print(key,value)

	def __delitem__(self, key):
		print(key)

li = Foo('zz', 18)  # 执行init方法
r=li[1:4:2]   # 自动执行li对象的类中的__getitem__方法,[1:4:2]当作参数传递给item
li[1:3:1] = [11,22]  # 自动执行li对象的类中的__setitem__方法,[1:3]和[11,22]传入
del li[1:3:1]  # 自动执行li对象的类中的__delitem__方法
class Foo:
	def __init__(self, name, age):
		self.name = name
		self.age = age

	def __add__(self, other):
		return Foo(obj1.name, other.age)

	def __del__(self):
		print('析构方法')
		# 对象被销毁时自动执行,没有人用时可以销毁,但是什么时候销毁不知道

obj1 = Foo('zz', 19)
obj2 = Foo('xx', 66)
r = obj1 + obj2
# 两个对象相加时,自动执行第一个对象的 __add__方法,并且将第二个对象当作参数传递进入
print(r.name,r.age) # zz 66


metaclass

# 先__new__创建对象  再__init__赋值
class MyType(type):
    def __init__(self,*args, **kwargs):
        print(1)
    def __call__(self, *args, **kwargs):
        print(2)
        r = self.__new__(1,2)  # ③执行Foo的 __new__
        self.__init__(self)  # ④执行Foo的init函数

# 创建类时用mytype
class Foo(object,metaclass=MyType):  # ①定义类时就执行MyType(type)的__init__()函数
    def __init__(self):
        print(4)
    def __new__(self, *args, **kwargs):
        print(3)
    def func(self):
        print('hello zz')

obj = Foo()  # ②执行MyType(type)的__call__()


单例,永远使用同一份实例(对象)

class Foo:
	__v = None
	@classmethod
	def get_instance(cls):
		if cls.__v:
			return cls.__v
		else:
			cls.__v = Foo( )
			return cls.__v

# 以下2个对象一模一样,内存也一样
obj1 = Foo.get_instance( )
obj2 = Foo.get_instance( )
print(id(obj1),id(obj2))


类的深浅拷贝


变量的赋值操作,只是形成了两个变量,实际上还是指向同一个对象

浅拷贝:

一般都为浅拷贝,拷贝时对象包含的子对象的内容不拷贝,因此原对象与拷贝对象会引用同个子对象

深拷贝:

copy模块的deepcopy函数,递归拷贝对象包含的子对象



版权声明:本文为weixin_49722641原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。