面向对象编程4

__ new __()

当使用"类名( [实参] ) "创建实例对象时,Python解释 器的主要处理过程包括两大步:
  1.调用特殊方法__ new___ ( )创建实例对象
首先会查找该类对象是否实现了特殊方法__ .new__ (), 如果没有实现,则去其父类中依次查找,直到类对象object。
  2.调用特殊方法_ init_ ( )对创建的实例对象进行初始化
__ new __ ( )返回的实例对象会作为实参被自动传递给_ init_ ()的第一 个形参self。

>>> class Parent (object) :
    	def  __new__ (cls, *args,**kwargs) :
    		pass
>>> class Chi ld (Parent):
    	def__ init_ (self, name) :
    		pass
>>> id(Parent)
> 74270440
>>> ud(Child)
> 74278936




>>> class Parent (object) :
    	def__ new__ (cls, *args, **kwargs) :
    		print("父类的__new__()被调用,其形参cls对应实参的id:",id(cls)) 	  	     		   				
    		id(c1s))obj = super0._ new__ (c1s)
      		print ("创建的实例对象的id:", id(obj))
      		return obj
>>> class Child (Parent) :
      		def__ init__ (self, name) :
			print("子类的__new__()被调用,其形参cls对应实参的id:"id(self))
			self. name = name
>>> child = Child(Mike")
> 父类的new__ () 被调用,其形参cls对应实参的id: 74269496创建的实例对象的id: 90380272
子类的__ init_ () 被调用,其形参self对应实参的id:90380272			

__ getitem ( )、 setitem __()、 __ delite __()

  对于自定义类对象的实例对象,在默认情况下,是不能像列表和字典那样使用中括号语法来操作数据的。

  如果想让自定义类对象的实例对象可以像列表和字典那样,使用中括号语法来操作数据,必须在自定义类对象中实现以下特殊方法:
1.__ getitem__ (self, key)
  当执行操作obj [key]时,会自动调用该特殊方法。
2. __ setitem __ (self, key, value)
  当执行操作obj [key] = vaLue时, 会自动调用该特殊方法。
3. __ delitem __ (self, key)
  当执行操作del obj [key]时,会自动调用该特殊方法。

>>> class MyDict (object):
			def_ init__ (self):
				self. data = {}
				
			def__ getitem__ (self, key):
				 return self. data[key]
				 
			 def__ setitem__ (self, key, value) :
				  self. data[key] = value

			 def__ delitem__ (self, key):
				del self. data [key]

>>> md = MyDict()

>>> md[" one"] = 18
>>> md["two"] = 32
>>> print (md. data)
{'one' : 18,'two':32}

__ call __( ) 与 callable()

  如果在类对象中实现了特殊方法call_ (), 那么就可以像调用函数-样直接调用这个类对象的实例对象,从而会自动调用特殊方法_ call_ ( )。

>>> class MyClass (object) :
			def_ ,call__ (self,  *args, *kwargs) :
				print (args, kwargs)

>>> mc = MyClass()
>>> mc()
> () {}

>>> mc(1,2,x=3,y=4)
> (1, 2) {'x': 3,y': 4}

  内置函数calLable用于判断指定对象是否是可调用的。
  除了函数对象是可调用的之外,对于实现了特殊方法_ call__ ( )的类对象,其实例对象也是可调用的。

__ doc __ 与 __ dict __

  调用内置函数dir得到的类对象的所有属性中,有一-个特殊属性叫__ doc_, 用于表示类对象的文档字符串。

一、什么是类对象的文档字符串(docstring)
  与函数的文档字符串类似,位于类对象的第一 行的字符串被称为类对象的文档字符串,通常用三个引号表示。类对象的文档字符串是对类对象的功能的简要描述。
二、访问类对象的文档字符串
  通过类对象的特殊属性_ doc_ 可以访问类对象的文档字符串。调用内置函数help( )得到的帮助信息中会包含类对象的文档字符串。

>>> class MyClass (object) :
			"""这是类对象的文档字符串
			1
			2
			3
			"""
			pass

>>> print (MyClass._ _doc_)
> 这是类对象的文档字符串
		1
		2
		3

  对于指定的类对象或实例对象,可以访问特殊属性_ dict 获得 该类对象或实例对象所绑定的所有属性和方法的字典。其中,字典中的键为属性名或方法名。

>>> class MyClass (object):
			ca="ca"
			
			def_ init__ (self):
				self.ia = "ia

			def im(self):
				pass

			@classmethoddef cm(cls):
				pass

			@stati cmethod
			def sm() :
				pass

>>> MyClass. ca2 = "ca2"
>>> MyClass._ _dict__

mappingproxy({'__ module__' : '_ main__',
						ca':' ca',
						'__init__ ': <function __main__ . MyClass. __ init__ (self)>,
					    'im':<function__main__. MyClass. im(self)>,
					    'cm': <classmethod at 0x56292b0>,
					    'sm' : Kstati cmethod at 0x5629ac8>,
						'__dict__': <attribute '__ dict__' of ' MyClass' objects>
						'__weakref__' :<attribute  '__ weakref__ ' of ' MyClass' objects>
						'__doc__' : None,
						ca2: 'ca2 '})

>>> mc = MyClass()
>>> mc. ia2 ="ia2"
>>> print(mc._ dict__)
> {'ia' : 'ia', 'ia2' : 'ia2' }

特殊属性之 __ slots __

  Python是动态语言,所以,在创建对象之后,可以对其动态地绑定属性和方法。
  如果想要对实例对象动态绑定的属性和方法的名称进行限制,可以在其对应的类对象中定义特殊属性__ slots__ 并给__ slots__ 赋值- 个所有元素都为字符串的列表或元组,这样,对实例对象动态绑定的属性和方法的名称就只能来自于__slots__ 中的元素。

  默认情况下,访问突例対象的属性是通过访问核突例対象的特殊属性__ dict__ 来实现的。例如:访问obj . x其实访问的是obj._dict [‘x’]

  在类対象中定义了特殊属性__ slots__ 后, 其实例対象就不会在创建特殊属性__ dict__ 了 ,而是为每个属性创建一个描述器,访问属性吋就会直接调用这个描述器。调用描述器比访问__dict__ 要快,因此,在类対象中|定义特殊属性 __ slots __ 可 以提高属性的访问速度。

  此外,在类対象中定义了特殊属性__slots__ 后, 由于其实例対象不再创建特殊属性__dict__ , 同肘,特殊属性__dict__ 是一个字典,字典的本质是哈希表,是一种用空囘換取时间的数据结构,因此,在类対象中定义特殊属性__slots__ 可以減少内存消耗。
  特殊属性__slots__ 只対其所在类対象的实例対象起作用, 対其所在类対象的子类的实例対象是不起作用的。
  如果子类也定义了特殊属性__slots__, 那么 子类的实例对象可以动态绑定的属性和方法的名称为子类的__slots__ 加上父类的__ slots__。

特殊方法之 __ len() __

  内置函数Len ( )用于返回对象的长度。
  内置函数Len ()的实参在默认情况下不能是自定义类对象的实例对象。

>>> print(len([1,2, 3, 4, 5]))
> 5
>>> print(len( abcde' ))
> 5
>>> print(len(a': 1, 'b': 2,'c': 3]))
> 3

  如果想让内置函数Len( )的实参可以是自定义类对象的实例对象,必须在自定义类对象中实现特殊方法__len__ ()。 这样,调用内置函数len()时,在其内部会自动调用实参所对应类对象的特殊方法__len__ ()。 之所以内置函数len() 的实参可以是上述内置类对象的实例对象,是因为上述的内置类对象中都实现了特殊方法__len__ ()。

生成器和迭代器

生成器(generater)

>>> [i * i for i in range(8)] #列表推导式
> [0, 1, 4, 9, 16, 25, 36, 49]
>>> (i * i for i in range(8))  #生成器表达式
> <generator object <genexpr> at 0x000001FA6DFD7FC0>
>>> a = (i * i for i in range(8))  #生成器是一次性的
>>> for i in a:
   			 print(i)
> 4
  9
  16
  25
  36
  49

生成器函数

  上面使用类似生成式的语法得到的生成器被称为生成器表达式。此外,当推算的算法比较复杂时,还可以使用生成器函数得到生成器。
  生成器函数中通过关键字yield返回推算出的元素。生成器函数与普通函数的区别在于:当调用内置函数next( )或使用for- in语句进行迭代时,执行完yield语句就会将生成器函数挂起,下次会从挂起的地方继续执行。

>>> def fib(n):
   	  i = 0
  	  a, b = 1,1
   	  while i < n:
      	 print(a,end = ',')
         a,b = b,a+b
     	 i += 1
>>> fib(6)
> 1,1,2,3,5,8,

>>> def fib(n):
  	  i = 0
      a, b = 1,1
      while i < n:
       	 yield a
       	 a,b = b,a+b
       	 i += 1
>>> fib(6)
> <generator object fib at 0x000001FA6E0C3468>
>>> next(fib(6))# 运行一次重启一次
> 1 #不管重复多少次运行,结果都是1
>>> gf = fib(6) #遇到yield就挂起,第二次运行yield后面的代码
>>> print(next(gf))
>>> print(next(gf))
>>> print(next(gf))
>>> print(next(gf))
>>> print(next(gf))
> 1
  1
  2
  3
  5

迭代器(iterator)

  可以用于for-in语句的对象被称为可迭代(iterable)对象。
   例如:range、列表、元组、字符串、字典、集合、生成器,都是可迭代对象。
  可以调用内置函数isinstance()判断一个对象是否是可迭代对象。标准库模块collections中的类iterable用于表示可迭代对象。
  能用内置函数next()调用的才是iterator

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值