PDA

View Full Version : هفته ای یک مقاله از پایتون



HackNetProg
پنج شنبه 15 مرداد 1394, 08:57 صبح
با سلام خدمت تمام پایتون کاران گرامی.

برای معرفی و ارتقای جایگاه پایتون در ایران در این قسمت سعی میکنیم به صورت هفتگی و رایگان مقالاتی را از خودم را اپلود کنم.

توجه کنید مقالات هیچ کدام کپی نیست و تماما حاصل دست نوشته های این گروه است.

فقط دوستان یک لطفی بکنند برای متمرکز شدن مطالب ؛

از دادن پست هایی برای بحث و نظر و تشکر خودداری نمایند تا مطاللب به صورت پشت سرهم و منظم قرار گیرد.

با تشکر

HackNetProg
پنج شنبه 15 مرداد 1394, 09:18 صبح
پایتون چیست ؟

http://2.bp.blogspot.com/-Yldpps5bJwc/VaHcW2JldaI/AAAAAAAAAE8/UReI7ZjTJp0/s320/1.jpg

شاید زمانی ک ب اسم پایتون فکر میکنید یاد جنگل امازون و مارهای غول پیکر پایتون بیوفتید اما اسم پایتون از یک مجموعه کمدی انتخاب شده است.
در ابتدا پایتون برای هکرها ساخته شد. به همین دلیل است که این زبان بعنوان زبان هکر ها انتخاب شده است.

اما با پیش رفت این زبان پایتون به یک زبان برنامه نویسی همه منظوره تبدیل شده است . یعنی در هر زمینه ای کار برد دارد!

شاید باور نکنید ولی حتی در زمینه فیلم سازی (https://www.python.org/success-stories/industrial-light-magic-runs-python/) هم کاربرد دارد.


ب طور کلی ابزار های مشهور در زمینه های مختلف برای زبان پایتون بصورت زیر است


Use Python for


Web Programming:
Django, Pyramid, Bottle, Tornado, Flask, web2py

GUI Development:
wxPython, tkInter, PyGtk, PyQt

Scientific and Numeric:
SciPy, Pandas, IPython

Software Development:
Buildbot, Trac, Roundup

System Administration:
Ansible, Salt, OpenStack


پشتیبان قدرتمند پایتون گوگل است و خالق این زبان در گوگل مشغول به کار است. همانطور ک گفتیم هرچند پایتون یک زبان همهاست اما روی شبکه به طرز عجیبی پیش تاز است.

http://1.bp.blogspot.com/-CpKnNgR4vdY/VaHdAJLpV3I/AAAAAAAAAFM/11TMzcQpUsg/s1600/HelloW-3.gif


اما بطور کلی امروزه طبق امار های رسمی زبان پایتون جزو پنج زبان اول دنیا تبدیل شده است و از لحاظ محبوبیت طبق امار ها محبوب ترین زبان 2015 است!











http://1.bp.blogspot.com/-cRKNNT5UWb4/VaHcggtEDbI/AAAAAAAAAFE/m7MdkjBtXvY/s320/2.jpg


سایت رسمی پایتون (https://www.python.org/)
https://Python.org (https://python.org/)


©نویسنده:pd
محصولات مارا در اینستاگرام و توییتر دنبال کنید👇
تیم ما یک سری محصول در زمینه های برنامه نویسی هک شبکه اماده میکنه
میتونید از طریق صفحه 👇 محصولات مارو پیگیری کنید
https://twitter.com/hacknetprog
https://instagram.com/p/5bccl2JHUs/
کپی فقط با ذکر منبع مجاز است. ©

HackNetProg
یک شنبه 18 مرداد 1394, 11:23 صبح
برنامه نویسی را از چه زبانی شروع کنم ؟



این سوال رایجی است که بین تمام کسانی که تازه میخواند به دنیای برنامه نویسی ورود کنند ؛ اپیدمیک میشود . در سایت ها و فروم های مختلف میشه این سوال رو از تازه کارا دید و جواب های بسیاری که هر کس بنا به اطلاعات خودش پاسخ داده و همیشه چون رسم بر این هست که از هرکسی بپرسید چه زبان بهتر است برای شروع؛ زبانی که خودش کار میکند را معرفی میکند و ادعا میکند که بهتر زبان دنیا را پیدا کرده است و شما هم باید ان را تجربه کنید.
از انجایی که بهترین زبان دنیا وجود ندارد(!) همچنین بیشتر این ادعاها زاییده ذهن توصیه کننده گان است مارا بر ان داشت که به طور بی طرفانه این موضوع را بررسی کنیم.
به این نکته توجه داشته باشید که ما در اینجا به مسایل که مربوط به زمان و دوره ای خاص هستن نمیپردازیم ، مثلا تا همین چند سال پیش جاوا در ایران بسیار پر طرفدار بود اما امروزه به خاطر بازار کاملا جایگاهش کم کم از دست میدهد. پس موضوع بحث ما ربطی به بازار و در امد ندارد بلکه میخواهیم زبانی را پیدا کنیم که بعد از فراگیری ان با مفاهیم برنامه نویسی به خوبی اشنا شده باشیم و بتوانیم در صورت نیاز به سرعت به زبان دیگری کوچ کنیم.
پس سوال را به این شکل تغییر میدهم، کدام زبان برای شروع بهتر است تا مفاهیم برنامه نویسی را به خوبی یاد بگیریم.
نکته ای که وجود دارد این است که، فردی که ادعای برنامه نویس بودن دارد حداقل به چند زبان باید مسلط و با چندین زبان اشنا باشد. پس زیاد درگیر این موضوع نشوید که چه زبانی را انتخاب کنیم که تا اخر عمر بتوانیم کنارش زندگی کنیم ! بلکه بجای ان باید دنبال زبانی باشید که سکویی پرتاب مناسبی برای شروع کار و حرکت به سمت زبان های دیگر باشد. حتی بدون توجه به بازار کار ان زبان! چون بعد از یادگیری زبان پایه اگر انتخاب مناسبی کرده باشید میتوانید به سرعت به زبان دیگری کوچ کنید.
دو برنامه نویس را در نظر بگیرید نفر اولی دانشجوی رشته کشاورزی است که بخاطر بازار خوب C# ، به وسیله چند اموزشگاه تبدیل به برنامه نویس C# شده است! نفر دوم هم دانشجوی کامپیوتری که چند زبان c/c++ را کاملا بلد است و با مفاهیم کامپیوتری اشنا است ولی به خاطر بازار خوب C# تصمیم میگیرد به C# کوچ کند . هر چند در ابتدای کار کند پیش میرود ولی حداکثر بعد یک ماه میتواند برنامه هایی که دانشجوی کشاورزی مینوشت را بنویسد! از نظر شما شاید این دو برنامه نویس هر دو یکسان باشند اما اتفاقی که می افتد این است که بازار ثابت نمی ماند!
فرض کنید به خاطر مذاکرات و خروج ایران از تحریم ها ، مشکلات کپی رایت محصولات کامپیوتری حل شود و از این پس ایرانی ها مجبور میشود که حق کپی رایت ماکروسافت را پرداخت کند. اتفاقی که می افتد این است که C# از مد می افتد!
حالا زمان کوچ به زبان دیگری رسیده است. به سراغ دانشجو ها میرویم . دانشجوی کشاورزی مفهوم برنامه نویسی را نمیداند و با C# کد میزند ولی نمیفهمد چرا این اتفاقات می افتد . دو راه دارد . یک کنار گذاشتن برنامه نویسی و رسیدن به حرفه ی خود مثلا دامداری(!) ؛ و اما راه دوم، به اموزشگاه برود پول خرج کند و دوباره با زبان جدید منطبق بازار اشنا شود. اما دانشجویی که با مفاهیم برنامه نویسی اشنا است نیازی به این کار ندارد 3هفته زمان نیاز دارد تا به زبان جدید کوچ کند.
برنامه نویسانی که به زبان های زیادی مسلط باشند به زمان کمتری برای کوچ کردن به زبان جدید نیاز دارند ، گاهی حتی چند روز کافی است! چون با مفاهیم کلی برنامه نویسی اشنا هستن، نیازی به یاد گیری و فهم انها نیست. واقعیت این است که مفاهیم در تمام زبان ها تقریبا ثابت اند! چیزی که تفاوت ایجاد میکند شکل مختلف کد ها هستن. مثلا تمام زبان ها حلقه و عبارات شرطی دارند منتها شکل ان ها متفاوت است.
پس نقطه ای که شما به عنوان ورود کننده به دنیای برنامه نویسی باید دنبالش باشید ، این نیست که زبانی را پیدا کنید که در حال حاضر بازار خوبی دارد و یا چون زبان راحتی برای یادگیری است. باید به دنبال زبانی باشید که بعد از ان به هر زبان دیگری که خواستید در عرض حداکثر یک ماه کوچ کنید.
برای شروع و یادگیری مفاهیم پایه ای برنامه نویسی من به شخصه زبان C++ را توصیه میکنم. ولی فقط برای یادگیری مفاهیم اصلی! مفاهیمی مثل متغییر ها ، حلقه ، عبارات شرطی و ... حتی این زبان مناسب یاد گیری مفاهیم مربوط به کلاس نیست!
برای یاد گیری مفاهیم کلاس حتما به سراغ جاوا بروید. جاوا شی گرایی اتو کشیده ای را ارائه میکند و سعی کرده که شبیه به کلاس های تئوری باشند و درصد زیادی هم موفق بوده. پس برای فردی که به دنبال یاد گیری مفاهیم اولیه کلاس ها است، بسیار مفید است.
سوال بعدی :
بعد از یاد گیری این مباحث چه کاری بکنیم ؟
واقعیت این است که، در عمل همیشه بحث متفاوت است! تئوریات در عمل همیشه جواب نمی دهند. همین مدل خوب جاوا برای شی گرایی در عمل برای ساخت کلاس های پیچیده تبدیل به غولی میشود که باید با ان دست و پنجه نرم کنید! پس چه باید کرد ؟ پاسخ کوچ کردن است از هر دو زبان جاوا و سی !
سوال بعدی این است که ایا چون با c c++ java شروع کردیم باید با همین ها ادامه دهیم؟
سوال اولیه ما این بود که چه زبانی برای شروع مناسب است ، بحث سر بهترین زبان دنیا برای زندگی کردن تا ابد نبود !! پس اگر به این نتیجه رسیدید که java و C++ زبان های خوبی برای ماندن برای ادامه زندگی تان هستن باید عرض کنم کاملا در اشتباهید!

سوال : به کجا باید رفت ؟
به جایی بروید که کد نویسی در ان راحت باشد ، کد های هزار خطی زبان C و 500 خطی java را در 100 خط بنویسید . زبانی که از کتابخانه های غنی ان لذت ببرید و خبری از پیچیدگی های زبان C++ و JAVA نباشد.
ایا چنین زبانی واقعا وجود دارد ؟ بله. زبان PYTHON دقیقا همین زبانی است که دنبال ان میگردید!
پایتون ؟ خب چرا از اول نگفتی؟
چون اگر از اول به سراغ پایتون بروید میشوید مثل همان دانشجوی کشاورزی!

©

©نویسنده:pd
محصولات مارا در اینستاگرام و توییتر دنبال کنید
تیم ما یک سری محصول در زمینه های برنامه نویسی هک شبکه اماده میکنه
میتونید از طریق صفحه محصولات مارو پیگیری کنید
https://twitter.com/hacknetprog
https://instagram.com/p/5bccl2JHUs/

کپی فقط با ذکر منبع مجاز است. ©

HackNetProg
پنج شنبه 22 مرداد 1394, 11:21 صبح
Decorators در پایتون


قبل از یک سری مسایل را باید بررسی کنیم. از functions شروع میکنیم.
در زبان پایتون functionها در واقع object هایی هستن که با انها میشود خیلی کارها را انجام داد.

>>> def f():
pass

>>> f
<function f at 0x02E157C8>
>>>
همانطور که میبینید خروجی f یک شی است. این شی را میتوان در یک متغییر دیگر ریخت و حتی ان را فراخوانی کرد!

>>> def f():
print('Hi F()')


>>> f
<function f at 0x029C5AE0>

>>> var=f
>>> var()
Hi F()

>>> f()
Hi F()

>>> del f
>>> f()
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
f()
NameError: name 'f' is not defined

>>> var()
Hi F()
>>>
میتوان یک function را داخل بدن یک function دیگر تعریف کرد:

>>> def outer():
def inner():
return('inner()')
return ("outer()")

>>> outer
<function outer at 0x02EB0C90>

>>> outer()
'outer()'

>>> outer()()
Traceback (most recent call last):
File "<pyshell#25>", line 1, in <module>
outer()()
TypeError: 'str' object is not callable

>>> x=outer()
>>> x
'outer()'

اگر برنامه را به شکل زیر عوض کنیم انگاه خطا هم حذف میشود:
>>> def outer():
def inner():
return('inner()')
return inner

>>> outer()()
'inner()'

>>> outer()
<function outer.<locals>.inner at 0x02EB0C90>

توجه کنید میتوان کد را به شکل زیر تغییر داد :

>>> def outer():
def inner():
return('inner()')
return inner()

>>> outer()
'inner()'
>>>
این اتفاقات بخاطر این است که از () برای فراخوانی توابع میتوان استفاده کرد. در کد دوم return inner() باعث فراخوانی این تابع میشود.
توابع را میتوان به عنوان ورودی به تابع دیگری داد و یکی را در درون دیگری صدا زد:

>>> def father():
return "Father"

>>> def call_fahter(f):
return (f()+'called')

>>> call_fahter(father)
'Fathercalled'
>>>
و کمی پیش رفته تر
>>> def say_hello(name):
return "hello"+name

>>> def send_name(func):
return func(" python!")

>>> send_name(say_hello)
'hello python!'
>>>

و خروجی یک تابع میتواند یک تابع باشد، حتی خودش میتواند خودش را بازگشت دهد:

>>> def main():
def sub_func():
print('subfunc')
return sub_func
return sub_func

>>> main()
<function main.<locals>.sub_func at 0x02E70348>

>>> main()()
subfunc
<function main.<locals>.sub_func at 0x02E70390>

>>> main()()()
subfunc
subfunc
<function main.<locals>.sub_func at 0x02E703D8>

>>> main()()()()
subfunc
subfunc
subfunc
<function main.<locals>.sub_func at 0x02E70420>


حالا به سراغ Decorators میرویم
به مثال زیر دقت کنید یک تابع داریم که در داخل بدنه اش یک تابع دیگر تعریف شده و بعنوان ورودی یک تابع را میگیرد :

>>> def make_bold(func):
def make_it(name):
return "<b>"+name+"</b>"
return make_it

>>> def get_name(name):
return name

>>> get_name("pd")
'pd'

>>> make_bold(get_name)
<function make_bold.<locals>.make_it at 0x02945AE0>

>>> make_bold(get_name)()
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
make_bold(get_name)()
TypeError: make_it() missing 1 required positional argument: 'name'

>>> make_bold(get_name("pd"))
<function make_bold.<locals>.make_it at 0x02DF0CD8>

>>> make_bold(get_name("pd"))()
Traceback (most recent call last):
File "<pyshell#14>", line 1, in <module>
make_bold(get_name("pd"))()
TypeError: make_it() missing 1 required positional argument: 'name'

>>> print(make_bold(get_name("pd")))
<function make_bold.<locals>.make_it at 0x02DF0D20>

>>> make_bold(get_name("pd"))("pd")
'<b>pd</b>'

>>> make_bold(get_name('pd'))("python")
'<b>python</b>'

اما این مثال یک مشکل دارد این که دو رشته نباید با هم متفاوت باشند. میشود انها را به شکل زیر تحصیح کرد.

>>> make_bold(get_name)('pd')
'<b>pd</b>'
حالا همین کاری که انجام دادیم را میتوان با Decorators به صورت اتوماتیک انجام دهیم.
منتها این بار به جای اینکه از سمت تابع کل به جز بریم کافیست تابع جزیی را صدا بزنیم:

def make_bold(func):
def make_it(name):
return "<b>"+func(name)+"</b>"
return make_it


@make_bold
def get_name(name):
return name


>>> get_name('pd')
'<b>pd</b>'
>>>

میبینید که تمام ان پیجیدگی ها نا پدید شدند!


©نویسنده:pd
محصولات مارا در اینستاگرام و توییتر دنبال کنید
تیم ما یک سری محصول در زمینه های برنامه نویسی هک شبکه اماده میکنه
میتونید از طریق صفحه محصولات مارو پیگیری کنید
https://twitter.com/hacknetprog
https://instagram.com/p/5bccl2JHUs/


کپی فقط با ذکر منبع مجاز است. ©

HackNetProg
چهارشنبه 28 مرداد 1394, 10:27 صبح
چرا "99" بزرگتر از "1111111111111111111" است ؟


اگر دستورات زیر را در زبان پایتون استفاده کنید شاید خروجی ان برای شما عجیب باشد.

>>> "99">"11111111"
True
>>> "99"<"11111111"
False
>>>

سوال این جاست که چرا این اتفاق رخ داده است ؟ و چرا از نظر پایتون "99">"11111111" است ؟
برنامه نویس در برنامه بالا دو منظور می توانسته داشته باشد.
1) مقایسه دو عدد.
2) مقایسه دو رشته
ابتدا فرض میکنیم منظور برنامه نویس مقایسه اعداد بوده . برنامه ی زیر را برای پیدا کردن ماکسیمم نوشته باشد.
این برنامه را به همراه خروجی ان در شکل زیر بررسی کنید.
تا زمانی که به 99 نرسیده ایم همه چیز درست به نظر می اید . اما بعد از اینکه 111111111 وارد شده، همه چیز به هم ریخت !
واقعیت این است که برنامه به درستی کار میکند! اشکال از درک ناصحیح برنامه نویسی است که برای مقایسه اعداد از فرمت رشته ها استفاده کرده است. در واقع برنامه نویس درک صحیحی از متغییر ها نداشته است.



number=input("Etr Num : ")
Max=""
while number.isdigit():
if number>Max :
Max=number
print(Max)
number=input("Etr Num : ")

Etr Num : 12
12
Etr Num : 10
12
Etr Num : 18
18
Etr Num : 99
99
Etr Num : 111111111
99






برای حل این مساله کافیست مقدار اولیه Max را بصورت عدد تعریف کنید مثلا Max=int() و در قدم بعدی ورودی که از کاربر میگیرید را به یک عدد تبدیل کنید.یعنی : Number=int(input())
سپس برنامه را اجرا کنید و از اینکه 99<11111111 است لذت ببرید!
اما چرا این اتفاق افتاد ؟
رشته ها در زبان پایتون به صورت Lexicographical_order مقایسه میشوند. یعنی به زبان ساده تر کارکتر به کاراکتر. در واقع وقتی 99 و 1111 را باهم مقایسه میکند از لحاظ رشته ها 99 بزرگتر است . چون که عمل مقایسه به این صورت شکل میگیرد ک:
ابتدا حرف اول دو رشته را باهم مقایسه میکند یعنی 1 و 9 چون 9 بزرگتر از 1 است به این نتیجه میرسد که 99 بزرگتر است. یک مثال دیگر را بررسی کنیم. دو رشته 191 و 1850 را باهم مقایسه کنیم. حروف اول هر دو 1 است پس باید به سراغ بقیه حروف رفت. حروف دوم 8 و 9 هستن . چون 9 بزرگتر از 8 است پس 191 بزرگتر است! یعنی مهم نیست که بعد از 8 دو رقم دیگر هم وجود دارد.




©نویسنده:pd
محصولات مارا در اینستاگرام و توییتر دنبال کنید
تیم ما یک سری محصول در زمینه های برنامه نویسی هک شبکه اماده میکنه
میتونید از طریق صفحه محصولات مارو پیگیری کنید
https://twitter.com/hacknetprog
https://instagram.com/p/5bccl2JHUs/
مقالات بیشتر
http://hacknetprog.blogspot.com/
کپی فقط با ذکر منبع مجاز است. ©

HackNetProg
پنج شنبه 05 شهریور 1394, 14:32 عصر
خواندن فایل های بزرگ در پایتون


کار کردن با فایل ها در پایتون به سادگی اب خوردن است! با یک خط دستور میتوان یک فایل را باز کرد و محتویات ان را خواند:


>>> open('e://big.txt','r').readline()
'The Project Gutenberg EBook of The Adventures of Sherlock Holmes\n'
>>>
بله به همین راحتی!
در این مقاله هدف مقایسه دو متد readline و readlines است. همونطور که از اسمشان پیداست هر دو قرار است فایل را بخوانند و خروجی را برمیگردانند:

>>> f=open('e://this.txt','r')
>>> f.readline()
'1abcde\n'
>>> f.readlines()
['2edf\n', '3hig\n', '4klm\n', '5opg\n']
>>>
اما یک تفاوت بزرگ در انها وجود دارد که در صورت عدم درک صحیح میتواند مشکل ساز شود.
فرض کنید یک فایل بزرگ را میخواهید با تو این دو متد بخوانید. حالا میخواهیم بررسی کنیم چه اتفاقی می افتد.
Readlines سعی میکند تمام فایل را بخواند و به صورت یک لیست که اعضای ان لیست توسط \n از هم جدا شده برگرداند. حالا اگر این فایل بزرگ باشد دو حالت پیش می اید.
حالت اول این که سیستم هنگ میکند و حالت دوم این که زمان بسیار زیادی طول میکشد که فقط همین دستور اجرا شود ، وقتی هیچ خروجی ای در کار نباشد کاربر تصور میکند که سیستم دچار هنگ شده و ان را ریست میدهد. به هر حال کار ناتمام میماند.
همانطور که میبینید خروجی های دو دستور زیر یکی است:

>>> f=open('e://this.txt','r')
>>> list(f)
['1abcde\n', '2edf\n', '3hig\n', '4klm\n', '5opg\n']
>>> f.readlines()
['1abcde\n', '2edf\n', '3hig\n', '4klm\n', '5opg\n']
سوالی که پیش می اید این است که ایا راه حل بهتری برای این کار وجود دارد یا خیر؟
راه حل های بسیاری وجود دارد و بهترین راه حل استفاده از فلسفه generator است.
ابتدا به سراغ راه حل ساده میرویم:
برای حل مسایل بزرگ شاید یکی از بهترین روش ها روش تقسیم و غلبه باشد. پس برای باز کردن و خواندن این فایل بزرگ میتوان انرا به صورت خط به خط خواند. یعنی :

>>> f=open('e://big.txt','r')
>>> f.readline()
'The Project Gutenberg EBook of The Adventures of Sherlock Holmes\n'
کافیست این کار توسط یک حلقه تکرار شود تا به پایان کار این فایل خوانده شود و چاپ شود. توجه کنید چیزی که در اینجا در مقایسه با برنامه بالایی تفاوت ایجاد میکند دو مساله است. اولا فایل را خط به خط میخوانیم. پس به شدت کمتری مصرف میکنیم . دوما نیازی نیست کاربر تا پایان کا منتظر خروجی بماند بلکه مرحله به مرحله خروجی را میتواند مشاهده کند.



for i in f:
print(i)

روشی بهتر:
زمانی که به این دسته مسایلی برخورد میکنید که نیاز به حافظه زیادی دارند بهترین روش استفاده از generator است. generator به دلیل تنبل بودن تولید را تا لحظه نهایی/دقیقا زمانی که نیاز باشد به عقب می اندازد. پس اگر از generator استفاده کنیم متغییری خواهیم داشت که حاوی اطلاعات تولید نشده فایل مورد نظر است که در حین نیاز انها را تولید میکند. این ویژگی دقیقا مشابه راه حل بالاست. اما به سراغ کد برویم. روش های زیادی وجود اما یک روش قشنگ :

>>> lines = tuple(open('e://this.txt', 'r'))
>>> lines
('1abcde\n', '2edf\n', '3hig\n', '4klm\n', '5opg\n')

>>> lines = tuple(open('e://big.txt', 'r'))
>>> for i in lines:
print(i)
در کد دوم تا زمانی که نوبت i به خط مورد نظر نرسیده باشد ان خط تولید نخواهد شده.
پس مرحله به مرحله جولو می رود و خط جاری را تولید و چاپ میکند. این روش با فایل های بزرگ هم مشکلی ندارد.
اما به عنوان اخرین راه حل .
میتوانید از تابع زیر برای خواندن فایل های بزرگ استفاده کنید»»» که بخاطر استفاده از generator ها هیچ وقت به مشکل حافظه بر نخواهید خورد.


def read_in_chunks(file_object, chunk_size=1024):
"""Lazy function (generator) to read a file piece by piece.
Default chunk size: 1k."""
while True:
data = file_object.read(chunk_size)
if not data:
break
yield data




f = open('really_big_file.dat')
for piece in read_in_chunks(f):
process_data(piece)



©نویسنده:pd
محصولات مارا در اینستاگرام و توییتر دنبال کنید
تیم ما یک سری محصول در زمینه های برنامه نویسی هک شبکه اماده میکنه
میتونید از طریق صفحه محصولات مارو پیگیری کنید
https://twitter.com/hacknetprog
https://instagram.com/p/5bccl2JHUs/

کپی فقط با ذکر منبع مجاز است. ©

HackNetProg
شنبه 07 شهریور 1394, 11:48 صبح
Self چیست و چرا در پایتون وجود دارد؟


به طور خلاصه Self به شی جاری اشاره میکند. در واقع وقتی از کلاس شی میسازید Self برابر شی ای هست که ساخته شده .
اما دلیل اینکه چرا در پایتون این عبارت وجود دارد. از زبان خود سازنده پایتون بشنوید:


With explicit references, there is no need to have a special syntax for method definitions nor do you have to worry about complicated semantics concerning variable lookup. Instead, one simply defines a function whose first argument corresponds to the instance, which by convention is named "self." For example:




def spam(self,y):
print self.x, y

جزییات بیشتر:

http://neopythonic.blogspot.com/2008/10/why-explicit-self-has-to-stay.html
https://docs.python.org/3.5/faq/design.html#why-must-self-be-used-explicitly-in-method-definitions-and-calls
http://python-history.blogspot.it/2009/02/adding-support-for-user-defined-classes.html

اما به طور خلاصه هدف متمایز کردن instance variables از سایر variable ها است
متدهای داخل یک کلاس را درپایتون میشود به چند دسته کلی تقسیم کرد. اولین و ساده ترین متد هایی هستن که با instance کار میکنند. به عبارت دیگر مخصوص شی ای هستن که ایجاد کرده اید.

doberman_instance =Dog('doberman') # call __init__(self, name) self = doberman_instance and name=doberman
>>> german_shepherd_instance=Dog('german shepherd')#call __init__(self, name) self = german_shepherd_instance and german shepherd
حالا دو سگ داریم یکی دوبرمن و دیگری ژرمن اطلاعات هر کدام از این سگ ها از دیگری مخفی و جدا نگهداری میشود و برای کار کردن با هر کدام باید به سراغ instance مربوط به خودش برویم.

>>> german_shepherd_instance.name
'german shepherd'
>>> german_shepherd_instance.bark(3)
german shepherd says: woof! woof! woof!
>>> doberman_instance.name
'doberman'
>>> doberman_instance.bark(4)
doberman says: woof! woof! woof! woof!
>>>
وقتی doberman_instance.bark را اجرا میکنید در واقع

self= doberman_instance
است و از این instance خاص متد مربوط به خودش را صدا میزند. چه کسی این تساوی را تنظیم کرد؟ خود پایتون. در حالت کلی دو راه وجود دارد یا خود شما بهش مقدار بدهید یا خودش سعی میکند مقدار بگیرد.

Dog.bark(doberman_instance,3)
در این مثل به عنوان اولین ورودی یعنی دقیقا بعنوان ورودی self مقدار doberman_instance را بطور دستی بهش دادیم.
ایا میتوان کلاسی در پایتون نوشت که از self برای کار کردن با مقادریر ان کلاس استفاده نکرد ؟
پاسخ بله است. البته تنها راه کار کردن با instance ها استفاده از self است اما میتوان کلاس را به شکلی نوشت که نیازی به ان نداشته باشد مثلا :


class Dog(object):
dog_counter=0
def __init__(self):
Dog.dog_counter+=1

def Print():
return Dog.dog_counter
doberman_instance =Dog()
Dog.Print()
#1
pitbull_instance =Dog()
Dog.Print()
#2

دقت کنید در هنگام استفاده از Print هیچ instance به متد ارسال نشده! اگر این کار را بکنید با مشکل برخواهید خورد :

doberman_instance.Print()#Error!
پایتون سعی میکند doberman_instance را ارسال کند اما چون به عنوان ورودی متد self وجود ندارد با خطا مواجه خواهیم شد.


Static Variables

این مفهوم هم در پایتون متفاوت از سایر زبان هاست! بسته به اینکه از متغییر تغییر پذیر استفاده میکنید یا تغییر ناپذیر:

class Dog:


age=int()


name=list()


def __init__(self,age,name):


Dog.age=age


Dog.name.append(name)





def Print(self):


print( Dog.age)


print( Dog.name)





doberman_instance=Dog(15,'doberman')


pitbull_instance =Dog(16,'pitbull')


doberman_instance.Print()


#16


#['doberman', 'pitbull']


چون لیست تغییر پذیر بود مقدار قبلی خود را فراموش نمیکند برعکس اعداد!



@staticmethod

نوع دیگر متد های وجود دارند که به انها @staticmethod میگویند.
این متد ها هیچ کاری با کلاس و instance ان کلاس ندارد! پس چرا انها را داخل کلاس مینویسیم ؟ یکی از اهداف دسته بندی این متد ها در کلاس ها مربوط به خودشان است.
اما کاربرد این متد در کجاست؟ اولا باید بگویم اگر static method جاوا دارید فکر میکنید باید بگویم کاملا در اشتباهید. کلا قضیه متفاوت است!
به کد زیر دقت کنید:

class Dog:
dogs = [] # this is a class variable

def __init__(self, name):
self.name = name #self.name is an instance variable
Dog.dogs.append(name)

def bark(self, n): # this is an instance method
print("{} says: {}".format(self.name, "woof! " * n))

def dog_list(): #this is implicitly a class method (see comments below)
for dog in Dog.dogs:
print(dog,end=', ')

doberman_instance=Dog('doberman')
pitbull_instance =Dog('pitbull')
Dog.dog_list()
#doberman,pitbull,

دقت کردید که Dog.dog_list را چطوری فراخوانی کردیم ؟ این متد مربوط به instance خاصی نمیشود! هیچ instance ای هم به ان متصل نیست!
خب مشکل در کجاست ؟ مشکل وقتی پیدا میشود که کاربرد میتواند این چنین ازین متد استفاده کند :

doberman_instance.dog_list()
#Error!
اتفاقی که می افتد این است که doberman_instance هم به عنوان ورودی self ارسال میشود اما این متدی که ما در کلاس تعریف کردیم چنین ورودی ای ندارد پس با خطا مواجه شدیم !
برای حل این مشکل از staticmethod استفاده میکنیم

class Dog:
dogs = [] # this is a class variable

def __init__(self, name):
self.name = name #self.name is an instance variable
Dog.dogs.append(name)

def bark(self, n): # this is an instance method
print("{} says: {}".format(self.name, "woof! " * n))

@staticmethod
def dog_list(): #this is implicitly a class method (see comments below)
for dog in Dog.dogs:
print(dog,end=', ')

doberman_instance=Dog('doberman')
pitbull_instance =Dog('pitbull')
Dog.dog_list()
doberman_instance.dog_list()
#doberman,pitbull,

این با پایتون این موضوع را میفهمد که قرار نیست به این متد هیچ doberman_instance ای عنوان ورودی self ارسال شود حتی اگر به این شکل کد را بنویسید :

doberman_instance.dog_list()

با هم چیزی ارسال نخواهد ش!
اما صبر کنید !! یک اشکالی وجود دارد . ما گفتیم که @staticmethod ها نه با کلاس و نه با instance ان کلاس کاری ندارد. اما در اینجا بر خلاف گفته هایمان عمل کردیم.
به طور خلاصه این طراحی ما ایراد دارد . هر طرحی که کار میکند دلیل بر صحیح بودن ان نیست. به طور کلی @staticmethod ها در پایتون خیلی کم استفاده میشوند و راه تشخیص اینکه ایا این متد که دارید از نوع @staticmethod هست یا نه این است که سعی کنید متد را از کلاس خارج کنید و در خارج کلاس باید همان کاری را کند که در داخل ان میکرد. اما نکته مهم این است که این متد ها کاری با کلاس و instance ندارند . یعنی میتوان کد زیر را به شکل زیر تغییر داد اما باز از کلاس داریم استفاده میکنیم:

class Dog:
dogs = [] # this is a class variable

def __init__(self, name):
self.name = name #self.name is an instance variable
Dog.dogs.append(name)

def bark(self, n): # this is an instance method
print("{} says: {}".format(self.name, "woof! " * n))


def dog_list():
for dog in Dog.dogs:
print(dog,end=', ')

doberman_instance=Dog('doberman')
pitbull_instance =Dog('pitbull')
dog_list()
#doberman,pitbull

این که بهترین روش پیاده سازی این مدل چیست مربوط به بخش بعدی میشود اما قبل ان یک مثال خوب از @staticmethod را بررسی کنیم:


class Date(object):
def __init__(self, day, month, year):
date=str(day)+str(month)+str(year)
if Date._check(date):
self.day = day
self.month = month
self.year = year


@staticmethod
def _check(date):
if date.isdigit():
return True
print('Date fortmat is: "dd-mm-yyyy ')
return False

دقت کنید به راحتی میتوان این متد را از کلاس خارج کرد.

@classmethod


و در نهایت به سراغ @classmethod میرویم. ویژگی این متدها این است که به عنوان اولین ورودی خود یک کلاس را میگیرند. اسم ان در پایتون ثابت است، cls . و همان قضیه های ارسال اتوماتیک که در مورد self بررسی کردیم هم اینجا وجود دارد. اما کاربردشان چیست ؟
اینبار میخواهیم کلاسی را طراحی کنیم که اشیای مربوط به دوبرمن ها و پیت بول ها را جداگانه نگه دارد . به مثال زیر دقت کنید:



class Dog():
_dogs = []

def __init__(self, name):
Dog._dogs.append(name)


class Doberman(Dog):
_doberman_dogs = []

def __init__(self, name):
self.name=name
Doberman._doberman_dogs.append(name)
super().__init__(name)

class Pitbull(Dog):
_pitbull_dogs = []

def __init__(self, name):
self.name=name
Pitbull._pitbull_dogs.append(name)
super().__init__(name)


>>> dp=Doberman('Doberman puppy')
>>> pp=Pitbull('Pitbull puppy')
>>> db1=Doberman('Doberman1')
>>> db2=Doberman('Doberman2')
>>> Doberman._doberman_dogs
['Doberman puppy', 'Doberman1', 'Doberman2']
>>> Pitbull._pitbull_dogs
['Pitbull puppy']

این همان چیزی بود که دنبالش بودیم. اما این طراحی را میتوان بهتر کرد. در زیر کلاس ها عبارت هایی دارد تکرار میشود قواعد طراحی شی گرا به ما میگوید که این عبارت ها را باید به ابر کلاس منتقل کنیم. و نکته اینجاست که در حین انتقال باز هم باید اشیای مربوط به دوبرمن ها و پیت بول ها را جداگانه نگه دارد . این همان جایی است که نیاز به @classmethod داریم. کد بالا را به شکل زیر تغییر میدهیم:




class Dog():
def __init__(self, name):
self._dogs.append(name)

@classmethod
def show(cls):
print( cls._dogs)

class Doberman(Dog):
_dogs = []
def __init__(self, name):
super().__init__(name)

class Pitbull(Dog):
_dogs = []
def __init__(self, name):
super().__init__(name)

dp=Doberman('dobi')
doberman=Doberman('dob')
pitbull=Pitbull('pit')
dp.show()
#['Doberman puppy', 'Doberman1']
pitbull.show()
#['Pitbull puppy']
Doberman.show()
#['Doberman puppy', 'Doberman1']
Dog.show()
#error
در واقع چیزی که در اینجا بررسی کردیم دست رسی ابر کلاس به زیر کلاس است ! چیزی که در زبان های دیگر به این سادگی قابل دست رس نیست !

اما این کد را میتوان به شکل هم تغییر داد ، یعنی دست رسی به همان خروجی بدون استفاده ازین مفهوم :




class Dog():
def __init__(self, name):
self._dogs.append(name)

def show(self):
print( self._dogs)

class Doberman(Dog):
_dogs = []
def __init__(self, name):
super().__init__(name)

class Pitbull(Dog):
_dogs = []
def __init__(self, name):
super().__init__(name)

dp=Doberman('dobi')
doberman=Doberman('dob')
pitbull=Pitbull('pit')
dp.show()
#['Doberman puppy', 'Doberman1']
pitbull.show()
#['Pitbull puppy']
Doberman.show()
#Error!
Dog.show()
#error
اما تفاوت در کجاست ؟
در کد دوم حتی دستور Doberman.show هم کار نمیکند. در واقع نیاز به instance داریم تا این دستور کار کند اما بخاطر ارث بری ها چنین گزینه ای وجود دارد. اما به روش زیر این کار انجام باید شود :

>>> Doberman.show(dp)
['dobi', 'dob']
که البته این دستور با وردوی dp بی معنی است ! برای حل این موضوع باید از @classmethod کنید در کد قبلی به این طریق با این متد کار میشد :

Doberman.show()
#['Doberman puppy', 'Doberman1']
که روشی صحیحی هم بود .


و اما پیاده سازی نهایی این کلاس به روش صحیح :




class Dog():
_dogs = []
def __init__(self, name):
if self.check_is_child():
self._dogs.append(name)#add to Dog subclass
Dog._dogs.append(name)
else:
raise NotImplementedError

def bark(self,n):
print("{} says: {}".format(self.name, "woof! " * n))

@classmethod
def show(cls):
return (cls._dogs)

@classmethod
def check_is_child(cls):
if cls.__name__ in (child.__name__ for child in Dog.__subclasses__()):
return True
return False

class Doberman(Dog):
_dogs = []
def __init__(self, name):
super().__init__(name)

class Pitbull(Dog):
_dogs = []
def __init__(self, name):
super().__init__(name)


dp=Doberman('Doberman puppy')
db1=Doberman('Doberman1')
pp=Pitbull('Pitbull puppy')
pp.show()
dp.show()
Doberman.show()
Dog.show()
d=Dog('dog')

HackNetProg
دوشنبه 16 شهریور 1394, 11:02 صبح
Metaclass چیست ؟


در اکثر زبان ها این قضیه بر قرار است :
کلاس توصیف کننده ی اشیای خودش است .اما به صرف تعریف کلاس شی ای تشکیل نمیشود و حافظه ای به ان اختصاص داده نمیشود.
وقتی از کلاس شی می سازیم این شی یک فضا را اشغال میکند. شی عینیت یافته را object گویند. به زبان پایتون یعنی :


class spam(): #تعریف کلاس
pass
Object=spam()#ساخت شی از کلاس
print(Object)
<__main__.spam object at 0x02D79670>


اما در پایتون این قضیه برقرار نیست . یعنی از انجایی که در پایتون نسخه 3 همه چیز شی هست، کلاس ها هم شی اند !



class spam():
pass
print(locals()['spam'])
<class '__main__.spam'>

این یعنی به محض تعریف کلاس حتی قبل از ایجاد یک instance این کلاس به عنوان یک شی در حافظه قرار دارد. خب ویژگی ها این این شی(کلاس spam) چیست ؟

· چون یک کلاس است پس میتوان از ان instance یا object ساخت و میتوان به ان method و attribute اضافه کرد و نکته مهم اینکه چون کلاس ها در پایتون شی اند میتوانید این کارها را on the fly انجام بدهید!
· چون شی است، مثل سایر اشیا در پایتون میتوان به راحتی کار با یک متغییر ساده با ان کار کرد. مثلا ان را در یک متغییر ریخت و میتوان ان را کپی کرد ویا به عنوان ورودی یک تابع پاس داد.
قبلا از type زیاد استفاده کردیم، در واقع type یک متغییر را نشان میداد . اما کاربردهایی مهم تر هم دارد! در واقع این type است که کلاس های شما را ایجاد میکند:



type(name of the class,
tuple of the parent class (for inheritance, can be empty),
dictionary containing attributes names and values)


در واقع وقتی کد زیر را اجرا میکنید


class Foo(object):
pass
اتفاقی که می افتد این است :


Foo = type('Foo', (), {}) # returns a class object
print(Foo)
print(Foo()) # create an instance with the class
گفتیم که type یک dictionary را به عنوان attribute های کلاس میگیرد . پس یعنی :



class Foo(object):
bar = True

بجاش میتوان نوشت :


Foo = type('Foo', (), {'bar':True})

و برای ارث بری داریم :



class FooChild(Foo):
'''
inherit from Foo
'''
pass
FooChild = type('FooChild', (Foo,), {})
print(FooChild)
print(FooChild.bar) # bar is inherited from Foo

نوبتی هم باشد حالا نوبت اضافه کردن method به کلاس است ، تنها کاری که باید بکنید این است که در جایگاه attribute ها ان را اضافه کنید. منتها به تفاوت بین attribute'name' و method echo_name دقت کنید. البته قبل ان باید method را تعریف کرده باشید.



#add methods to your class
def echo_name(self):
print(self.name)

Foo= type('Foo', (), {'name':'pd','echo_name': echo_name})
foo = Foo()
foo.echo_name()



این کار ها دقیقا همان کاری است پایتون برای شما به طور اتوماتیک انجام میدهد .


خب به همان سوال اصلی بر میگردیم . metaclass چیست ؟
ابتدا چند تعریف را بررسی میکنیم.
· Metaclass یعنی class of a class .
· همانطور که کلاس ایجاد گر instance است ؛ metaclass ایجادگر یک class است. پس class یک instance از metaclass است.
· metaclass در واقع type کلاس را مشخص میکند.
· در واقع پایتون وقتی به عبارت class میرسد با استفاده از صدا زدن metaclass یک class ایجاد میکند. برای انجام اینکار از متد های زیر استفاده میکند.
__init__ ، __new__
· type در پایتون یک metaclass است. دیدید چطوری باهاش کلاس میشه ساخت.
· type خودش یک class است و چون ازش برای ساخت class استفاده میشود بهش class of a class میگوییم.
· type از نوع type است .
· در پایتون type را نمیتوانید تغییر دهید اما میتوانید یک metaclass دلخواه ایجاد کنید.
پس به طور خلاصه ما برای ساخت یک instance از class کمک میگیریم ، اما از انجایی که همه چیز در پایتون نسخه 3 شی است، class ها هم شی اند . چه کسی این شی class را میسازد ؟ پاسخ metaclass است.
تمام این حرف ها را به زبان پایتون میشود خلاصه کرد :



MyClass = MetaClass()
MyObject = MyClass()

و



number=int()
string=str()
dictionary=dict()
Class=type('Class',(),{})

type(number)
number.__class__ # class of number => int
number.__class__.__class__# class of class of number or
# class of int => type

number.__class__.__class__.__class__ # class of class of class of number
# or class of type => type


به همین راحتی !

و در ادامه کاربرد های metaclass ها را خواهیم دید.

یک مثال خوب از متا کلاس در پایتون ورژن 2 :



def make_hook(f):
"""Decorator to turn 'foo' method into '__foo__'"""
f.is_hook = 1
return f


class MyType(type):
def __new__(cls, name, bases, attrs):


if name.startswith('None'):
return None


# Go over attributes and see if they should be renamed.
newattrs = {}
for attrname, attrvalue in attrs.iteritems():
if getattr(attrvalue, 'is_hook', 0):
newattrs['__%s__' % attrname] = attrvalue
else:
newattrs[attrname] = attrvalue


return super(MyType, cls).__new__(cls, name, bases, newattrs)


def __init__(self, name, bases, attrs):
super(MyType, self).__init__(name, bases, attrs)


# classregistry.register(self, self.interfaces)
print "Would register class %s now." % self


def __add__(self, other):
class AutoClass(self, other):
pass
return AutoClass
# Alternatively, to autogenerate the classname as well as the class:
# return type(self.__name__ + other.__name__, (self, other), {})


def unregister(self):
# classregistry.unregister(self)
print "Would unregister class %s now." % self


class MyObject:
__metaclass__ = MyType




class NoneSample(MyObject):
pass


# Will print "NoneType None"
print type(NoneSample), repr(NoneSample)


class Example(MyObject):
def __init__(self, value):
self.value = value
@make_hook
def add(self, other):
return self.__class__(self.value + other.value)


# Will unregister the class
Example.unregister()


inst = Example(10)
# Will fail with an AttributeError
#inst.unregister()


print inst + inst
class Sibling(MyObject):
pass


ExampleSibling = Example + Sibling
# ExampleSibling is now a subclass of both Example and Sibling (with no
# content of its own) although it will believe it's called 'AutoClass'
print ExampleSibling
print ExampleSibling.__mro__


اما شاید یکی از بهترین کاربرد های متا ها را میتوان در جانگو دید :


https://docs.djangoproject.com/en/dev/topics/db/models/#meta-options

https://docs.djangoproject.com/en/1.8/topics/db/models/





©نویسنده:pd
محصولات مارا در اینستاگرام و توییتر دنبال کنید
تیم ما یک سری محصول در زمینه های برنامه نویسی هک شبکه اماده میکنه
میتونید از طریق صفحه محصولات مارو پیگیری کنید

https://twitter.com/hacknetprog
https://instagram.com/p/5bccl2JHUs/


کپی فقط با ذکر منبع مجاز است. ©

ASedJavad
شنبه 28 شهریور 1394, 22:36 عصر
سلام دوست عزیز
دو هفته گذشت ها!!!!

HackNetProg
دوشنبه 30 شهریور 1394, 14:36 عصر
چرا در پایتون مقدار دهی در عبارات شرطی و حلقه ها ممکن نیست؟




در زبان هایی مثل C و C++‎‎‎‎‎‎‎‎‎‎ عبارتی مثل عبارت های زیر بدون مشکلی اجرا میشوند .



while (line = readline(file)) {
...do something with line...
}




و یا



if (match = search(target)) {
...do something with match...
}


ویا

if (int x=1)
{
cout<<"ok";
}





اما پایتون اجازه تعریف چنین عبارتی را به شما نمیدهد . پایتون دلیل خود را دارد و هدف ما ازین مقاله بررسی هدف پایتون است.
در مثال های بالا منظور از عبارت if(x=y) به این معنی نیست که اگر x برابر y بود این شرط صحیح است بلکه به این معنی است که که مقدار y را در x بریز. سپس y را فراموش کن و بررسی کن که مقداری که داخل x است True هست یا نه. و دقیقا مشکل از زمانی به وجود می اید که عبارت مقایسه ای x==y به عنوان یکی از پرکاربردترین شرط های ، عبارت شرطی است و به این معنی است که x را با y مقایسه کن اگر برابر بودند حاصل True است. یکی از اشتباهات رایج برنامه نویسان استفاده از عبارت x=y به جای x==y است. اگر شما هم برنامه نویس c/C++‎‎‎‎‎‎‎‎‎‎ باشید بعید است که چنین خطایی را نکرده باشید. پس این ویژگی باعث مستعد شدن برنامه به باگ میشود و چه بسا برنامه های بزرگی که بخاطر یک = کمتر کلی هزینه ایجاد کردند.



if (x = 0) {
...error handling...
}
else {
...code that only works for nonzero x...
}





این برنامه دقیقا همان مشکلی را دارد که راجبش صحبت کردیم. مطمعنا منظور برنامه نویس در عبارت شرطی مقایسه x با عدد صفر بود اما برنامه از اول 0 را درون x میریزد و عبارت شرطی به طور کامل غلط در نظر گرفته میشود.
حالا میخواهیم همان برنامه ها را به سبک پایتون بنویسیم.
برنامه دوم:



match = search(target)
if match:
... do something with match ...




همانطور که میبینید تنها کاری که کردیم مقدار دهی match در یک خط بالاتر بود. به همین راحتی !
اما برنامه اول :





for line in file:
... do something with line ...





ویا میتوان به صورت while نوشت:



while True:
line = file.readline()
if not line:
break
... do something with line ...




و یا


line = f.readline()
while line:
...do something with line...
line = f.readline()




البته مثال اولی کد بهتری است. ولی اما این کد را میتوان بهتر ازین هم نوشت .حالتی که هم حافظه را بهینه تر مصرف کنید هم خطای کمتری داشته باشد. مثلا :



for line in iter(f.readline, ""):
... do something with line ...




در واقع با استفاده از iter قابلیت حلقه زدن روی اطلاعاتی که از فایل می اید را به ما میدهد و به سادگی یک لیست می توان روی ان حلقه زد.
پس پایتون اجازه استفاده از عبارت = را در حلقه و عبارت شرطی به ما نمیدهد چون هم یکی از مشکلات رایج برنامه نویسان است و هم راه حل های بهتری در اختیار برنامه نویسان میگذارد که میتوان از انها استفاده کرد.




©نویسنده:pd
محصولات مارا در اینستاگرام و توییتر دنبال کنید
تیم ما یک سری محصول در زمینه های برنامه نویسی هک شبکه اماده میکنه
میتونید از طریق صفحه محصولات مارو پیگیری کنید

https://twitter.com/hacknetprog
https://instagram.com/p/5bccl2JHUs/
کپی فقط با ذکر منبع مجاز است. ©

HackNetProg
پنج شنبه 14 آبان 1394, 16:10 عصر
فرض کنید یک متن دلخواه داریم و میخواهیم این متن را به وسیله ی یک برنامه کامپیوتری حدس بزنیم. یک روش تولید تمام حالات ممکن است و هر دفعه مقدار تولیدی را با متن نهایی مقایسه کنیم و این کار را تا زمانی که این دو متن یکسان شوند ادامه دهیم. این نوعی الگوریتم کورکورانه است و برای تولید متن نهایی حالت های زیادی را باید تست کرد. فرض کنید اگر این متن ما بین 1 تا 10 کاراکتر باشد و به ازای هر جایگاه 26 حرف انگلیسی را چایگزین کنیم اون موقع تمام حالات از قرار زیر میشود:

اگر متن از یک کاراکتر تشکیل شده باشد و ان کاراکتر حروف کوچک باشد انگاه حالات ممکن میشود:


a-z

یعنی 26 حالت را تولید میکنیم و مقایسع میکنیم.

اگر متن ما یک یا دو کاراکتر داشته باشد میشود، هر جایگاه 26 حالت که میشود :


26*26


حالا سه حالت :

26*26*26

و هینطور 10 حالت میشود 26 به توان 10. عدد بزرگی میشود. حالا ترکیب حروف کوچک و بزرگ را به ان اضافه کنید و همینطور اعداد و سایر کارکتر ها را در نهایت حاصل به خاطر هزینه ی زیاد دز زمان دست نیافتنی خواند بود !

اما راه حل چیست ؟
میتوان نوعی روش تولید کرد که به جای جست و حوی کور کورانه فاصله اش را هر بار تا مقصد بسنجد واگر با برداشتن قدم نزدیک میشود ان قدم را بردارد وگرنه راه دیگری را تست کند.

با این فلسفه کار را شروع میکنیم. هر هر بار به ازای کاراکتری که قرار است تولید شود فاصله را میسنجیم اگر نزدیک تر میشدم قدم برداریم و این به زبان پایتون یعنی :



def fitness (source, target):
fit_val=(ord(source)-ord(target))**2
return fit_val



اول به سراغ این مساله برویم که چرا به توان دو رسیده است حاصل به این طریق اگر حاصل منتها منفی شود ان به عدد مثبتی تبدیل خواهد شد. به مثال زیر دقت کنید و دریابید چرا اعداد منفی محاسبات ما را بهم میریزد .
این تابع دو ورودی دارد . یکی جایگاهی(کاراکتر) که هستیم و دیگری جایگاه مقصد و فاصله این دو را به ما میدهد. تنها کاری که کردایم این است که کاراکتر را به کد اسکی مربوطه اش تبدیل کردیم و سپس این اعداد را از هم کم کردیم. فرض کنید اگر
a=97
b=98
c=99
باشد انگاه مبدا b باشد و مقصد c. حالا از b شروع میکنیم عدد b نود و هشت است اکر یکی به ان اضافه کنیم میشود 99 ؛ مقصد 99 است و فاصله صفر میشود یعنی به مقصد رسیده ایم. اما اگر به جای اضافه کردن از ان کم میکردیم 97 حاصل میشود چون از مقصد یکی دور شدیم پس مسیر غلط است و ادامه نمیدهیم.
نکته ای که میماند این است که به مبدا باید اضافه کنیم یا کم کنیم ؟ برای این کار تابع زیر را مینویسیم که به طور تصادفی کم یا اضافه کند:



def mutate(char):
return chr(ord(char)+random.choice((1,-1)))




و در نهایت کاری که میخواهم انجام دهیم این است که ببنیم که ایا اضافه/کم کردن موجب نزدیک شدن به مقصد شده ؟ اگر نشده حرکت نکنیم و مسیر دیگری را تست کنیم :



while fitness_val !=0:
m=mutate(char)
fit=fitness(m, target[index])
if fit < fitness_val:
fitness_val=fit
chars=list(source)
chars[index]=m
source="".join(chars)
char=m


و حالا ترکیب تمام این کد ها میشود همان برنامه ای که دز زمان کوتاهی رشته ی مورد نظر شما را پیدا میکند :



import random


def fitness (source, target):
fit_val=(ord(source)-ord(target))**2
return fit_val


def mutate(char):
return chr(ord(char)+random.choice((1,-1)))




if __name__=='__main__':
target = "Catch Me If You Can!!!"
source=" "*len(target)
print("init: ", source)
for index,char in enumerate(source):
fitness_val=fitness(char,target[index])
print("_"*5,"\nindex: ", index)
while fitness_val !=0:
m=mutate(char)
fit=fitness(m, target[index])
if fit < fitness_val:
fitness_val=fit
chars=list(source)
chars[index]=m
source="".join(chars)
char=m
print("\t",source)
print("final: ", char)


print("final string: " ,source )




این برنامه کاراکتر به کاراکتر تست میکند و در هر مرحله سعی میکند به مقصد نزردیکتر شود تا در نهایت متن شما را به دست میاورد. خروحی برنامه به طور خلاصه :




_____
index: 0
!
"
#
$
%
&
'
(
)
*
+
,
-
.
/
0
1
2
3
4
5
6
7
8
9
:
;
<
=
>
?
@
A
B
C
final: C
_____
index: 1
C!
C"
C#
C$
C%
C&
C'
C(
C)
C*
C+
C,
C-
C.
C/
C0
C1
C2
C3
C4
C5
C6
C7
C8
C9
C:
C;
C<
C=
C>
C?
C@
CA
CB
CC
CD
CE
CF
CG
CH
CI
CJ
CK
CL
CM
CN
CO
CP
CQ
CR
CS
CT
CU
CV
CW
CX
CY
CZ
C[
C\
C]
C^
C_
C`
Ca
final: a
_____
index: 2
Ca!
Ca"
Ca#
Ca$
Ca%
Ca&
Ca'
Ca(
Ca)
Ca*
Ca+
Ca,
Ca-
Ca.
Ca/
Ca0
Ca1
Ca2
Ca3
Ca4
Ca5
Ca6
Ca7
Ca8
Ca9
Ca:
Ca;
Ca<
Ca=
Ca>
Ca?
Ca@
CaA
CaB
CaC
CaD
CaE
CaF
CaG
CaH
CaI
CaJ
CaK
CaL
CaM
CaN
CaO
CaP
CaQ
CaR
CaS
CaT
CaU
CaV
CaW
CaX
CaY
CaZ
Ca[
Ca\
Ca]
Ca^
Ca_
Ca`
Caa
Cab
Cac
Cad
Cae
Caf
Cag
Cah
Cai
Caj
Cak
Cal
Cam
Can
Cao
Cap
Caq
Car
Cas
Cat
final: t
_____
index: 3
Cat!
Cat"
Cat#
Cat$
Cat%
Cat&
Cat'
Cat(
Cat)
Cat*
Cat+
Cat,
Cat-
Cat.
Cat/
Cat0
Cat1
Cat2
Cat3
Cat4
Cat5
Cat6
Cat7
Cat8
Cat9
Cat:
Cat;
Cat<
Cat=
Cat>
Cat?
Cat@
CatA
CatB
CatC
CatD
CatE
CatF
CatG
CatH
CatI
CatJ
CatK
CatL
CatM
CatN
CatO
CatP
CatQ
CatR
CatS
CatT
CatU
CatV
CatW
CatX
CatY
CatZ
Cat[
Cat\
Cat]
Cat^
Cat_
Cat`
Cata
Catb
Catc
final: c
.
.
.

Catch Me If You C"
Catch Me If You C#
Catch Me If You C$
Catch Me If You C%
Catch Me If You C&
Catch Me If You C'
Catch Me If You C(
Catch Me If You C)
Catch Me If You C*
Catch Me If You C+
Catch Me If You C,
Catch Me If You C-
Catch Me If You C.
Catch Me If You C/
Catch Me If You C0
Catch Me If You C1
Catch Me If You C2
Catch Me If You C3
Catch Me If You C4
Catch Me If You C5
Catch Me If You C6
Catch Me If You C7
Catch Me If You C8
Catch Me If You C9
Catch Me If You C:
Catch Me If You C;
Catch Me If You C<
Catch Me If You C=
Catch Me If You C>
Catch Me If You C?
Catch Me If You C@
Catch Me If You CA
Catch Me If You CB
Catch Me If You CC
Catch Me If You CD
Catch Me If You CE
Catch Me If You CF
Catch Me If You CG
Catch Me If You CH
Catch Me If You CI
Catch Me If You CJ
Catch Me If You CK
Catch Me If You CL
Catch Me If You CM
Catch Me If You CN
Catch Me If You CO
Catch Me If You CP
Catch Me If You CQ
Catch Me If You CR
Catch Me If You CS
Catch Me If You CT
Catch Me If You CU
Catch Me If You CV
Catch Me If You CW
Catch Me If You CX
Catch Me If You CY
Catch Me If You CZ
Catch Me If You C[
Catch Me If You C\
Catch Me If You C]
Catch Me If You C^
Catch Me If You C_
Catch Me If You C`
Catch Me If You Ca
final: a
_____
index: 18
Catch Me If You Ca!
Catch Me If You Ca"
Catch Me If You Ca#
Catch Me If You Ca$
Catch Me If You Ca%
Catch Me If You Ca&
Catch Me If You Ca'
Catch Me If You Ca(
Catch Me If You Ca)
Catch Me If You Ca*
Catch Me If You Ca+
Catch Me If You Ca,
Catch Me If You Ca-
Catch Me If You Ca.
Catch Me If You Ca/
Catch Me If You Ca0
Catch Me If You Ca1
Catch Me If You Ca2
Catch Me If You Ca3
Catch Me If You Ca4
Catch Me If You Ca5
Catch Me If You Ca6
Catch Me If You Ca7
Catch Me If You Ca8
Catch Me If You Ca9
Catch Me If You Ca:
Catch Me If You Ca;
Catch Me If You Ca<
Catch Me If You Ca=
Catch Me If You Ca>
Catch Me If You Ca?
Catch Me If You Ca@
Catch Me If You CaA
Catch Me If You CaB
Catch Me If You CaC
Catch Me If You CaD
Catch Me If You CaE
Catch Me If You CaF
Catch Me If You CaG
Catch Me If You CaH
Catch Me If You CaI
Catch Me If You CaJ
Catch Me If You CaK
Catch Me If You CaL
Catch Me If You CaM
Catch Me If You CaN
Catch Me If You CaO
Catch Me If You CaP
Catch Me If You CaQ
Catch Me If You CaR
Catch Me If You CaS
Catch Me If You CaT
Catch Me If You CaU
Catch Me If You CaV
Catch Me If You CaW
Catch Me If You CaX
Catch Me If You CaY
Catch Me If You CaZ
Catch Me If You Ca[
Catch Me If You Ca\
Catch Me If You Ca]
Catch Me If You Ca^
Catch Me If You Ca_
Catch Me If You Ca`
Catch Me If You Caa
Catch Me If You Cab
Catch Me If You Cac
Catch Me If You Cad
Catch Me If You Cae
Catch Me If You Caf
Catch Me If You Cag
Catch Me If You Cah
Catch Me If You Cai
Catch Me If You Caj
Catch Me If You Cak
Catch Me If You Cal
Catch Me If You Cam
Catch Me If You Can
final: n
_____
index: 19
Catch Me If You Can!
final: !
_____
index: 20
Catch Me If You Can!!
final: !
_____
index: 21
Catch Me If You Can!!!
final: !
final string: Catch Me If You Can!!!
>>>


این برنامه کاراکتر به کاراکتر به دنبال مقصد میگردد اما میتوان برنامه را طوری نوشت که در هر بار کل متن را تصادفی تولید و مقایسه کند :




import random
import string
target = "Catch Me If You Can!!!"
source =" "*len(target)
def fitness(source, target):
fitval = 0
for i in range(0, len(source)):
fitval += (ord(target[i]) - ord(source[i]))**2
return(fitval)


def mutate(source):
charpos = random.randint(0, len(source) - 1)
parts = list(source)
parts[charpos] = chr(ord(parts[charpos]) + random.randint(-1,1))
return("".join(parts))


fitval = fitness(source, target)
i = 0
while True:
i += 1
m = mutate(source)
fitval_m = fitness(m, target)
if fitval_m < fitval:
fitval = fitval_m
source = m
print ("%5i %5i %14s" % (i, fitval_m, m))
if fitval == 0:
break





خلاصه خروجی :



7 63717 !
10 63578 !!
11 63411 ! !!
14 63322 ! ! !!
17 63157 " ! !!
23 63014 " ! ! !!
34 62901 " ! ! !! !
36 62772 " ! ! !! ! !
40 62703 ! " ! ! !! ! !
44 62540 ! # ! ! !! ! !
45 62461 ! # ! ! "! ! !
48 62460 ! # ! ! "! ! ! !
51 62393 " # ! ! "! ! ! !
66 62264 "!# ! ! "! ! ! !
67 62103 "!$ ! ! "! ! ! !
68 61970 "!$!! ! "! ! ! !
.
.
.
589 316 Cakch Me Ie Yhj Caf!!!
4595 301 Cakch Me Ie Yhj Cag!!!
4609 300 Cakch Me If Yhj Cag!!!
4650 279 Cakch Me If Yhk Cag!!!
4681 260 Cakch Me If Yhl Cag!!!
4694 243 Cakch Me If Yhm Cag!!!
4695 228 Cakch Me If Yhn Cag!!!
4701 215 Cakch Me If Yho Cag!!!
4746 202 Cakch Me If Yho Cah!!!
4769 191 Cakch Me If Yho Cai!!!
4790 174 Calch Me If Yho Cai!!!
4808 165 Calch Me If Yho Caj!!!
4838 152 Calch Me If Yio Caj!!!
4842 141 Calch Me If Yip Caj!!!
4845 130 Calch Me If Yjp Caj!!!
4871 123 Calch Me If Yjp Cak!!!
4888 114 Calch Me If Yjq Cak!!!
4918 109 Calch Me If Yjq Cal!!!
4920 106 Calch Me If Yjq Cam!!!
5076 97 Calch Me If Ykq Cam!!!
5092 90 Calch Me If Ykr Cam!!!
5100 75 Camch Me If Ykr Cam!!!
5112 74 Camch Me If Ykr Can!!!
5150 69 Camch Me If Yks Can!!!
5152 62 Camch Me If Yls Can!!!
5202 57 Camch Me If Yms Can!!!
5206 54 Camch Me If Yns Can!!!
5207 53 Camch Me If Yos Can!!!
5238 40 Canch Me If Yos Can!!!
5267 37 Canch Me If Yot Can!!!
5316 36 Canch Me If You Can!!!
5343 25 Caoch Me If You Can!!!
5506 16 Capch Me If You Can!!!
5547 9 Caqch Me If You Can!!!
5601 4 Carch Me If You Can!!!
5721 1 Casch Me If You Can!!!
5794 0 Catch Me If You Can!!!



کاملترین اموزش برنامه نویسی پایتون به زبان فارسی
کلیک کنید (http://rayka-co.ir/online-shop/programming/%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%A8%D9%87-%D8%B3%D8%A8%DA%A9-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-detail)