<p>이 기사에서는 <a href="http://www.php.cn/course/list/31.html" target="_blank">Python</a>에 대한 관련 지식을 제공합니다. Python에는 메서드 이름이 이중 밑줄로 시작하고 끝나는 몇 가지 특수 메서드가 있으므로 이를 함께 살펴보겠습니다. 모든 사람. </p>
<p><img src="https://img.php.cn/upload/article/000/000/067/62d4f1fd38dfa174.jpg" alt="Python의 더블다운 방법을 완전히 마스터하세요." ></p>
<p>【관련 추천: <a href="http://www.php.cn/course/list/31.html" target="_blank">Python3 동영상 튜토리얼</a>】</p>
<h2>머리말</h2>
<p>파이썬 코드를 작성할 때 이런 질문이 있으신가요? </p>
<p>수학에서 <code>+</code> 기호가 <code>'ab' + 'cd'</code>와 같은 문자열 연산에서 연결 함수로 바뀌고 결과가 <code>abcd; <code>*</code> 숫자는 <code>'ab' * 2</code>와 같이 반복되는 함수가 되며 결과는 <code>abab</code>입니다. <code>+</code>号,在字符串运算中却变成拼接功能,如<code>'ab' + 'cd'</code>结果为<code>abcd</code>;而<code>*</code>号变成了重复功能,如<code>'ab' * 2</code>结果为<code>abab</code>。</code></p>
<p>为什么某些对象<code>print</code>能输出数据,而<code>print</code>自定义的类对象却输出一堆看不懂的代码<code><__main__.MyCls object at 0x105732250></code>。</p>
<p>不是因为系统做了特殊定制,而是 Python 中有一类特殊的方法,在某些特定的场合会自动调用。如,在字符串类<code>str</code>中定义了<code>__add__</code>方法后,当代码遇到字符串相加<code>'ab' + 'cd'</code>时,就会自动调用<code>__add__</code>方法完成字符串拼接。</p>
<p>因为这类特殊方法的方法名都是以双下划线开始和结束,所以又被称为双下方法。</p>
<p>Python 中的双下方法很多,今天我们对它做个详解。</p>
<p style="text-align:center"><img alt="" src="https://img.php.cn/upload/article/000/000/067/dc4eae5d11b7bd06ec193c866274280b-0.jpg"></p>
<p style="text-align:center">Python中的双下方法</p>
<h2>1. init方法</h2>
<p><code>__init__</code>的方法是很多人接触的第一个<code>双下方法</code>。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">class A:
def __init__(self, a):
self.a = a</pre><div class="contentsignin">로그인 후 복사</div></div><p>当调用<code>A()</code>实例化对象的时候,<code>__init__</code>方法会被自动调用,完成对象的初始化。</p><h2>2. 运算符的双下方法</h2><p>在类中定义运算符相关的<code>双下方法</code>,可以直接在类对象上做加减乘除、比较等操作。</p><p>这里,定义一个尺子类<code>Rule</code>,它包含一个属性<code>r_len</code>代表尺子的长度。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">class Rule:
def __init__(self, r_len):
self.r_len = r_len</pre><div class="contentsignin">로그인 후 복사</div></div><h3>2.1 比较运算符</h3><p>如果想按照尺子的长度对不同的尺子做比较,需要在<code>Rule</code>类中定义比较运算符。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">class Rule:
def __init__(self, r_len):
self.r_len = r_len
# < 运算符
def __lt__(self, other):
return self.r_len < other.r_len
# <= 运算符
def __le__(self, other):
return self.r_len <= other.r_len
# > 运算符
def __gt__(self, other):
return self.r_len > other.r_len
# >= 运算符
def __ge__(self, other):
return self.r_len >= other.r_len</pre><div class="contentsignin">로그인 후 복사</div></div><p>这里定义了<code><</code>、<code><=</code>、<code>></code>和<code>>=</code>四个比较运算符,这样就可以用下面的代码比较<code>Rule</code>对象了。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">rule1 = Rule(10)
rule2 = Rule(5)
print(rule1 > rule2) # True
print(rule1 >= rule2) # True
print(rule1 < rule2) # False
print(rule1 <= rule2) # False</pre><div class="contentsignin">로그인 후 복사</div></div><p>当用<code>></code>比较<code>rule1</code>和<code>rule2</code>的时候,<code>rule1</code>对象会自动调用<code>__gt__</code>方法,并将<code>rule2</code>对象传给<code>other</code>参数,完成比较。</p><p>下面是比较运算符的双下方法</p><p style="text-align:center"><img alt="" src="https://img.php.cn/upload/article/000/000/067/dc4eae5d11b7bd06ec193c866274280b-1.png"/></p><p style="max-width:90%">比较运算符双下方法</p><h3>2.2 算术运算符</h3><p>可以支持类对象加减乘除。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">def __add__(self, other):
return Rule(self.r_len + other.r_len)</pre><div class="contentsignin">로그인 후 복사</div></div><p>这里定义了<code>__add__</code>方法,对应的是<code>+</code>运算符,他会把两个尺子的长度相加,并生成新的尺子。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">rule1 = Rule(10)
rule2 = Rule(5)
rule3 = rule1 + rule2</pre><div class="contentsignin">로그인 후 복사</div></div><p>下面是算术运算符的双下方法</p><p style="text-align:center"><img alt="" src="https://img.php.cn/upload/article/000/000/067/dc4eae5d11b7bd06ec193c866274280b-2.png"/></p><h3>2.3 反向算术运算符</h3><p>它支持其他类型的变量与<code>Rule</code>类相加。以<code>__radd__</code>方法为例</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">def __radd__(self, other):
return self.r_len + other</pre><div class="contentsignin">로그인 후 복사</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">rule1 = Rule(10)
rule2 = 10 + rule1</pre><div class="contentsignin">로그인 후 복사</div></div><p>程序执行<code>10 + rule1</code>时,会尝试调用<code>int</code>类的<code>__add__</code>但<code>int</code>类类没有定义与<code>Rule</code>类对象相加的方法,所以程序会调用<code>+</code>号右边对象<code>rule1</code>的<code>__radd__</code>方法,并把<code>10</code>传给<code>other</code>参数。</p><p>所以这种运算符又叫右加运算符。它所支持的运算符与上面的算术运算符一样,方法名前加<code>r</code>即可。</p><h3>2.4 增量赋值运算符</h3><p>增量赋值运算符是<code>+=</code>、<code>-=</code>、<code>*=</code>、<code>/=</code>等。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">def __iadd__(self, other):
self.r_len += other
return self</pre><div class="contentsignin">로그인 후 복사</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">rule1 = Rule(10)
rule1 += 5</pre><div class="contentsignin">로그인 후 복사</div></div><p>除了<code>__pmod__</code>方法,其他的跟算数运算符一样,方面名前都加i。</p><h3>2.4 位运算符</h3><p>这部分支持按二进制进行取反、移位和与或非等运算。由于<code>Rule</code>类不涉及位运算,所以我们换一个例子。</p><p>定义二进制字符串的类<code>BinStr</code>,包含<code>bin_str</code>属性,表示二进制字符串。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">class BinStr:
def __init__(self, bin_str):
self.bin_str = bin_str</pre><div class="contentsignin">로그인 후 복사</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">x = BinStr('1010') #创建二进制字符串对象
print(x.bin_str) # 1010</pre><div class="contentsignin">로그인 후 복사</div></div><p>给<code>BinStr</code>定义一个取反运算符<code>~</code></p>일부 개체 <code>print</code>는 데이터를 출력할 수 있지만 <code>print</code> 사용자 정의 클래스 개체는 이해할 수 없는 코드 묶음을 출력하는 이유 <code><__main__.MyCls object at 0x105732250></code >. 🎜🎜시스템을 특별히 맞춤화해서가 아니라, Python에는 특정 경우에 자동으로 호출되는 특별한 유형의 메서드가 있기 때문입니다. 예를 들어, 문자열 클래스 <code>str</code>에서 <code>__add__</code> 메서드를 정의한 후 코드에서 문자열 추가 <code>'ab' + 'cd'</code>를 발견하면 <code>__add__</code> 메서드는 문자열 접합을 완료하기 위해 자동으로 호출됩니다. 🎜🎜이러한 특수 메서드의 메서드 이름은 이중 밑줄로 시작하고 끝나기 때문에 이중 밑줄 메서드라고도 합니다. 🎜🎜파이썬에는 더블다운(Double-Down) 메소드가 많이 있습니다. 오늘은 이에 대해 자세히 설명하겠습니다. 🎜<p style="text-align:center"><img alt="" src="https://img.php.cn/upload/article/000/000/067/dc4eae5d11b7bd06ec193c866274280b-0.jpg"/> 🎜<p style="max-width:90%">Python의 더블다운 방식🎜🎜1.init 방식🎜🎜<code>__init__</code> 방식은 많은 사람들이 찾아오는 첫 번째 <code>더블 다운로드 방식입니다. 메소드</code>와 접촉합니다. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;"># ~ 运算符
def __invert__(self):
inverted_bin_str = ''.join(['1' if i == '0' else '0' for i in self.bin_str])
return BinStr(inverted_bin_str)</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div>🎜<code>A()</code>를 호출하여 개체를 인스턴스화하면 <code>__init__</code> 메서드가 자동으로 호출되어 개체 초기화를 완료합니다. 🎜🎜2. 연산자의 더블다운 방식🎜🎜클래스에서 덧셈, 뺄셈, 곱셈, 나눗셈, 비교 등의 연산을 직접 수행할 수 있는 연산자 관련 <code>더블다운 방식</code>을 정의합니다. 클래스 객체. 🎜🎜여기서 눈금자의 길이를 나타내는 <code>r_len</code> 속성이 포함된 눈금자 클래스 <code>Rule</code>을 정의하세요. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">x = BinStr('1011')
invert_x = ~x
print(invert_x.bin_str) # 0100</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><h3>2.1 비교 연산자</h3>🎜 길이에 따라 서로 다른 눈금자를 비교하려면 <code>Rule</code> 클래스에서 비교 연산자를 정의해야 합니다. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">def __repr__(self):
decimal = int('0b'+self.bin_str, 2)
return f'二进制字符串:{self.bin_str},对应的十进制数字:{decimal}'</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div>🎜여기에는 <code><</code>, <code><=</code>, <code>></code> 및 <code>>=</code>의 네 가지 비교가 정의되어 있습니다. 다음 코드를 사용하여 <code>Rule</code> 객체를 비교할 수 있도록 연산자를 사용합니다. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">x = BinStr('1011')
print(x)
# 输出:二进制字符串:1011,对应的十进制数字:11</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div>🎜<code>></code>를 사용하여 <code>rule1</code>과 <code>rule2</code>를 비교하면 <code>rule1</code> 개체가 자동으로 <code>를 호출합니다. __gt__</code> 메서드를 사용하고 <code>rule2</code> 개체를 <code>other</code> 매개변수에 전달하여 비교를 완료합니다. 🎜🎜다음은 비교연산자의 더블클릭 방식입니다🎜<p style="text-align:center"><img alt="" src="https://img.php.cn/upload/article/ 000/000 /067/dc4eae5d11b7bd06ec193c866274280b-1.png"/>🎜<p style="max-width:90%">비교 연산자 더블다운 방식🎜<h3>2.2 산술 연산자</h3>🎜덧셈, 뺄셈 지원 가능 , 클래스 객체의 곱셈과 나눗셈. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">def __format__(self, format_spec):
return format_spec % self.bin_str</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div>🎜여기서 <code>+</code> 연산자에 해당하는 <code>__add__</code> 메서드가 정의되어 있습니다. 이 메서드는 두 눈금자의 길이를 더하고 새 눈금자를 생성합니다. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">print('{0:二进制字符串:%s}'.format(x))
# 输出:二进制字符串:1011</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div>🎜다음은 산술연산자의 더블클릭 방법입니다🎜<p style="text-align:center"><img alt="" src="https://img.php.cn/upload/article/ 000/ 000/067/dc4eae5d11b7bd06ec193c866274280b-2.png"/>🎜<h3>2.3 역산술 연산자</h3>🎜<code>Rule</code> 클래스를 사용하여 다른 유형의 변수 추가를 지원합니다. <code>__radd__</code> 메소드를 예로 들어보세요🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">def __int__(self):
return int('0b'+self.bin_str, 2)</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">x = BinStr('1011')
print(int(x))</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div>🎜프로그램이 <code>10 + rule1</code>을 실행할 때 <code>의 <code>__add__</code> 호출을 시도합니다. >int</code> 클래스 그러나 <code>int</code> 클래스는 <code>Rule</code> 클래스 객체를 추가하는 메서드를 정의하지 않으므로 프로그램은 <code>rule1< 객체를 호출합니다. / <code>+</code> 숫자 code>의 <code>__radd__</code> 메소드 오른쪽에 <code>10</code>을 <code>other</code>에 전달합니다. 매개변수. 🎜🎜그래서 이 연산자를 오른쪽 덧셈 연산자라고도 합니다. 지원하는 연산자는 위의 산술 연산자와 동일합니다. 메소드 이름 앞에 <code>r</code>만 추가하면 됩니다. 🎜<h3>2.4 증분 할당 연산자</h3>🎜 증분 할당 연산자는 <code>+=</code>, <code>-=</code>, <code>*=</code> , <code >/=</code> 등 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">def __len__(self):
return len(self.bin_str)
def __getitem__(self, item):
return self.bin_str[item]</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">x = BinStr('1011')
print(len(x)) # 4
print(x[0]) # 1
print(x[0:3]) # 101</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div>🎜<code>__pmod__</code> 메서드를 제외하고 다른 모든 것은 산술 연산자와 동일하며 측면 이름 앞에 i를 추가합니다. 🎜<h3>2.4비트 연산자</h3>🎜이 부분은 부정, 시프트, AND 또는 NOT과 같은 이진 연산을 지원합니다. <code>Rule</code> 클래스에는 비트 연산이 포함되지 않으므로 예제를 변경해 보겠습니다. 🎜🎜바이너리 문자열을 정의하는 <code>BinStr</code> 클래스에는 바이너리 문자열을 나타내는 <code>bin_str</code> 속성이 포함되어 있습니다. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">def __iter__(self):
self.cur_i = -1
return self
def __next__(self):
self.cur_i += 1
if self.cur_i >= len(self.bin_str):
raise StopIteration() # 退出迭代
return self.bin_str[self.cur_i]</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">x = BinStr('1011')
for i in x:
print(i)</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div>🎜 <code>BinStr</code>에 대한 부정 연산자 <code>~</code>🎜 정의<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;"># ~ 运算符
def __invert__(self):
inverted_bin_str = ''.join(['1' if i == '0' else '0' for i in self.bin_str])
return BinStr(inverted_bin_str)</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><p><code>__invert__</code>方法中,遍历<code>bin_str</code>字符串,将每位取反,并返回一个新的<code>BinStr</code>类对象。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">x = BinStr('1011')
invert_x = ~x
print(invert_x.bin_str) # 0100</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><p>下面是位运算符的双下方法</p><p style="text-align:center"><img alt="" src="https://img.php.cn/upload/article/000/000/067/4894e53be3e9850194264d258e8620e0-3.png"/></p><p>这部分也支持反向位运算符和增量赋值位运算符,规则跟算数运算符一样,这里就不再赘述。</p><h2>3.字符串表示</h2><p>这部分涉及两个双下方法<code>__repr__</code>和<code>__format__</code>,在某些特殊场景,如<code>print</code>,会自动调用,将对象转成字符串。</p><p>还是以<code>BinStr</code>为例,先写<code>__repr__</code>方法。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">def __repr__(self):
decimal = int('0b'+self.bin_str, 2)
return f'二进制字符串:{self.bin_str},对应的十进制数字:{decimal}'</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">x = BinStr('1011')
print(x)
# 输出:二进制字符串:1011,对应的十进制数字:11</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><p>当程序执行<code>print(x)</code>时,会自动调用<code>__repr__</code>方法,获取对象<code>x</code>对应的字符串。</p><p>再写<code>__format__</code>方法,它也是将对象格式化为字符串。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">def __format__(self, format_spec):
return format_spec % self.bin_str</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">print('{0:二进制字符串:%s}'.format(x))
# 输出:二进制字符串:1011</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><p>当<code>.format</code>方法的前面字符串里包含<code>0:</code>时,就会自动调用<code>__format__</code>方法,并将字符串传给<code>format_spec</code>参数。</p><h2>4.数值转换</h2><p>调用<code>int(obj)</code>、<code>float(obj)</code>等方法,可以将对象转成相对应数据类型的数据。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">def __int__(self):
return int('0b'+self.bin_str, 2)</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">x = BinStr('1011')
print(int(x))</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><p>当调用<code>int(x)</code>时,会自动调用<code>__int__</code>方法,将二进制字符串转成十进制数字。</p><p>数值转换除了上面的两个外,还有<code>__abs__</code>、<code>__bool__</code>、<code>__complex__</code>、<code>__hash__</code>、<code>__index__</code>和<code>__str__</code>。</p><p><code>__str__</code>和<code>__repr__</code>一样,在<code>print</code>时都会被自动调用,但<code>__str__</code>优先级更高。</p><h2>5.集合相关的双下方法</h2><p>这部分可以像集合那样,定义对象长度、获取某个位置元素、切片等方法。</p><p>以<code>__len__</code>和<code>__getitem__</code>为例</p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">def __len__(self):
return len(self.bin_str)
def __getitem__(self, item):
return self.bin_str[item]</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">x = BinStr('1011')
print(len(x)) # 4
print(x[0]) # 1
print(x[0:3]) # 101</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><p><code>len(x)</code>会自动调用<code>__len__</code>返回对象的长度。</p><p>通过<code>[]</code>方式获取对象的元素时,会自动调用<code>__getitem__</code>方法,并将切片对象传给<code>item</code>参数,即可以获取单个元素,还可以获取切片。</p><p>集合相关的双下方法还包括<code>__setitem__</code>、<code>__delitem__</code>和<code>__contains__</code>。</p><h2>6.迭代相关的双下方法</h2><p>可以在对象上使用<code>for-in</code>遍历。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">def __iter__(self):
self.cur_i = -1
return self
def __next__(self):
self.cur_i += 1
if self.cur_i >= len(self.bin_str):
raise StopIteration() # 退出迭代
return self.bin_str[self.cur_i]</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">x = BinStr('1011')
for i in x:
print(i)</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><p>当在<code>x</code>上使用<code>for-in</code>循环时,会先调用<code>__iter__</code>方法将游标<code>cur_i</code>置为初始值<code>-1</code>,然后不断调用<code>__next__</code>方法遍历<code>self.bin_str</code>中的每一位。</p><p>这部分还有一个<code>__reversed__</code>方法用来反转对象。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">def __reversed__(self):
return BinStr(''.join(list(reversed(self.bin_str))))</pre><div class="contentsignin">로그인 후 복사</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">x = BinStr('1011')
reversed_x = reversed(x)
print(reversed_x)
# 输出:二进制字符串:1101,对应的十进制数字:13</pre><div class="contentsignin">로그인 후 복사</div></div><h2>7.类相关的双下方法</h2><p>做 web 开发的朋友,用类相关的双下方法会更多一些。</p><h3>7.1 实例的创建和销毁</h3><p>实例的创建是<code>__new__</code>和<code>__init__</code>方法,实例的销毁是<code>__del__</code>方法。</p><p><code>__new__</code>的调用早于<code>__init__</code>,它的作用是创建对象的实例(内存开辟一段空间),而后才将该实例传给<code>__init__</code>方法,完成实例的初始化。</p><p>由于<code>__new__</code>是类静态方法,因此它可以控制对象的创建,从而实现<strong>单例模式</strong>。</p><p><code>__del__</code>方法在实例销毁时,被自动调用,可以用来做一些清理工作和资源释放的工作。</p><h3>7.2 属性管理</h3><p>类属性的访问和设置。包括<code>__getattr__</code>、<code>__getattribute__</code>、<code>__setattr__</code>和<code>__delattr__</code>方法。</p><p><code>__getattr__</code>和<code>__getattribute__</code>的区别是,当访问类属性时,无论属性存不存在都会调用<code>__getattribute__</code>方法,只有当属性不存在时才会调用<code>__getattr__</code>方法。</p><h3>7.3 属性描述符</h3><p>控制属性的访问,一般用于把属性的取值控制在合理范围内。包括<code>__get__</code>、<code>__set__</code>和<code>__delete__</code>方法。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">class XValidation:
def __get__(self, instance, owner):
return self.x
def __set__(self, instance, value):
if 0 <= value <= 100:
self.x = value
else:
raise Exception('x不能小于0,不能大于100')
def __delete__(self, instance):
print('删除属性')
class MyCls:
x = XValidation()
def __init__(self, n):
self.x = n
obj = MyCls(10)
obj.x = 101
print(obj.x) # 抛异常:Exception: x不能小于0,不能大于100</pre><div class="contentsignin">로그인 후 복사</div></div><p>上述例子,通过类属性描述符,可以将属性x的取值控制在<code>[0, 100]</code>之前,防止不合法的取值。</p>
<h2>8.总结</h2>
<p>虽然上面介绍的不是所有的双下方法,但也算是绝大多数了。</p>
<p>虽然双下方法里可以编写任意代码,但大家尽量编写与方法要求一样的代码。如,在<code>__add__</code>方法实现的不是对象相加而是相减,虽然也能运行,但这样会造成很大困惑,不利于代码维护。</p>
<p>【相关推荐:<a href="http://www.php.cn/course/list/31.html" target="_blank">Python3视频教程</a> 】</p>
위 내용은 Python의 더블다운 방법을 완전히 마스터하세요.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!