🐍 Python & Raspberry 🐍
8.08K subscribers
1.92K photos
125 videos
623 files
1.23K links
Python- Raspberry Pi-AI-IOT
ادمین : فرهاد ناصری زاده
@farhad_naserizadeh
@farhad3412

گروه پایتون
@Python_QA
تبادل
@mmtahmasbi
کانال مرتبط
@new_mathematical
@micropython_iot
@c_micro
اینستاگرام
http://Instagram.com/python_raspberry
Download Telegram
Power :)

#m4hdi

©@raspberry_python
🔥7👍2
What our BDFL said :)

https://github.com/python/cpython/issues

#m4hdi
〰️〰️〰️〰️〰️
©@raspberry_python
👍2
با این اوصاف اینجا دیگه پای سلیقه و موقعیت شما میاد وسط و اصلا نمیتونیم بگیم کدوم روش درست یا درست‌تره! و هر روش خوبی و بدی و طرفدار و مخالفی داره

[اگر] بگیم روش اول درست نیست، پاسخ میگیریم که خیر ۱. در stdlib استفاده شده، یعنی core devهای پایتون ازش استفاده کردن و ۲. تعداد خطوط کمی رو اشغال کرده و مرتب و خوانا شده.
[اگر] بگیم روش black درست نیست، باید بگیم که اولا black توسط یکی از core devهای پایتون که در فیس‌بوک کار می‌کرد به اسم Lukas Langa نوشته شده و ۲۷ هزار ستاره گیت‌هاب داره 😃✌️
و در چنین پروژه‌ها و شرکت‌‌هایی استفاده میشه
https://github.com/psf/black#used-by

ثانیا اگه پای type annotations توی کد بیاد وسط روش اول اصلا قشنگ نمیشه!

Answers: 1 • 2 • 3

#M4hdi
〰️〰️〰️〰️〰️
©️@raspberry_python
👍3
یه خوبی دیگه‌‌ای که بلک داره اینه که اگه می‌خواید پارارمتر‌های تابع رو type annotate کنید، با این روش این کار به زیبایی صورت میگیره، و هر خط نام پارامتر و تایپی که قراره بگیره و نشون میده، اما در روش اول زیادی شلوغ میشه 😬

Answers: 1 • 2 • 3

#M4hdi
〰️〰️〰️〰️〰️
©️@raspberry_python
👍4
Organize Python code like a PRO 🐍📦

پروژه‌تون رو مثل یک حرفه‌ای ساختاربندی و مرتب کنید.

از اونجایی که پایتون یک زبان خیلی منعطف هست (مثل جاوا نیست که وقتی یه فایل جاوا درست میکنید باید یه کلاسِ پابلیک به همون اسم داخلش باشه) شما این اجازه رو دارید که کل کد یک پروژه رو توی یک فایل، و یا هر تابع رو توی یک فایل جدا بنویسید 😑🥴

با این مقاله یاد بگیرید که چگونه پروژه‌تون رو درست ساختار بندی کنید.

https://guicommits.com/organize-python-code-like-a-pro/

#M4hdi

©@raspberry_python
👍4👎1
✔️ سوال.

بهترین راه برای فهمیدن اینکه یه آبجکت hashable هست، چیه؟!

جوابتون رو کامنت کنید.

پاسخش رو فردا میگذارم.

#M4hdi
〰️〰️〰️〰️〰️〰️
©@raspberry_python
خب شاید پیش خودتون بگید، آبجکتی که داندر hash داشته باشه حتما hashable عه دیگه، این داندر رو داره و جوابتون این باشه:

o = obj
if hasattr(o, '__hash__'):
print(f"{o} is hashable")

اما خیر 😁

اول یه چیز پایه‌ای بگیم.
کلاس آبجکت object پایه‌ای ترین base class در پایتونه و اینکه میگن همه‌چیز در پایتون آبجکته، یکی از دلیلاش اینه. هر چیزی که فکرش رو بکنید از object ارث می‌بره.

این کلاس کلی داندر متد داره و از قضا دو تا داندر که در این مطلب برای ما مهم هستن رو هم با هم داره

داندر eq -> برای چک کردن تساوی دو تا آبجکت
obj1 == obj2
داندر hash -> برای برگرداندن مقدار hash آبجکت که از تابع hash میگیریم
hash(obj)

وقتی یک کلاسی شما می‌نویسید:
class Spam:
pass

این کلاس به طور خودکار از کلاس آبجکت ارث می‌بره که تبعا داندر متد‌ها براش resolve میشن، که یعنی، ارث‌‌شون میبره، یا اینکه میگرده توی کلاس object پیدا شون میکنه.

نکته‌ی داندر eq
رفتار پیش‌فرض داندر eq به این صورته که میان آیدی‌های دو آبجکت رو باهم مقایسه میکنه. یعنی اگه اون رو override نکرده باشید و بخواید آبجکت‌هاتون رو با هم مقایسه کنید، وقتی جواب True میگیرید که دو تا آبجکت در واقع یک آبجکت باشن. دقیقا همون کاری که is انجام میده.

s1 = s2 = Spam()
s1 == s2 -> True

اما شاید چنین رفتاری رو نخواید و جور دیگه‌ای بخوایید که آبجکت‌های شما تساوی‌شون چک بشه
خب میاید داندر eq رو جوری که میخواید اورراید میکنید

اما 😁

وقتی این کار رو کردید، اتفاقی که میوفته اینه که مقدار داندر hash شما None میشه و آبجکت شما دیگه hashable نیست
این یعنی دیگه نمی‌تونید توی دیکشنری و ست بذاریدش و ....

این در حالیه که آبجکت شما همچنان داندر hash داره ولی hashable نیست.

این توضیحات میشن دلیل اینکه چرا اون شرط باگ داره.

اما راه‌حل چیه؟
خب شاید بیاید بگید بجای اینکه چک کنیم هست، چک میکنیم که None نباشه

if o.__hash__ is not None:
...

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

class Spam:
def __eq__(self): ...

Spam.hash = "Gotcha, Im neither hashable nor None =)"

پس بهترین راه‌حل چیه؟
It is easier to ask forgiveness than permission

try:
hash(o)
except TypeError:
print("unhashable")
else:
print("hashable")

اما یه سوال بی جواب میمونه!
بالاتر گفتیم اگه داندر eq رو اورراید کنیم آبجکت ما دیگه hashable نیست و توی ست و دیکشنری نمی‌تونیم استفاده کنیم. من میخوام اون ور اورراید کنم و بازم hashable باشه 😒😒

خب جوابش ساده‌ست

شما باید داندر hash رو هم اورراید کنید و یه مقدار int برگردونید

نکته‌ای که هست و باید بهش توجه داشته باشید اینه که باید بتونید یه عددی تولید کنید که تکراری شدنش سخت باشه (اگه تکراری بشه اشکالی نداره) و به ویژگی‌های آبجکت شما وابسته هم باشه (حتما قرار نیست به ویژگی‌هاش وابسته باشه، اما اگه باشه، اون نکته‌ی قبلی راحت‌تر بدست میاد)

برای مثال
class Spam:
def __init__(self, name):
self.name = name

def __eq__(self):
...

def __hash__(self):
return hash(self.name)

تبعا شما اسامی مختلفی قراره به هر آبجکت که از Spam درست میکنید بدید، و این باعث میشه که hash هر بار فرق کنه

اما اگه اسم یکسان هم بدید، مشکلی نیست یه قانونی هست توی بحث hash که میگه:
اگر دو آبجکت دقیقا یکسان باشن، (یعنی دو تا رفرنس از یک آبجکت رو داشته باشیم) باید hash یکسانی داشته باشن
اما اگر ما دو تا hash یکسان از دو تا آبجکت داشتیم، الزاما اون دو آبجکت یکی نیستن.

به این حالت که هش یکسانه ولی آبجکتا یکی نیستن، میگن hash collision. که پایتون خودش این رو هندل میکنه
و بحثش در این مقال "دیگر 😮‍💨" نمیگنجد.

موفق باشید 😁✌️

#M4hdi
〰️〰️〰️〰️〰️〰️〰️
©@raspberry_python
👍14
✔️ فرض کنیم چنین سوالی داریم

"میخوایم ببینیم، آیا حرف nام letters در کلمه nام words وجود داره یا نه"

دو راه داریم که مشخص شدن.

بدون ران کردن و تست سرعت کد، این خیلی مهمه، بگید کدوم کند‌تره؟

و برای جواب‌تون حتما دلیل بتراشید

[خط سوم (choice) درست هست]
#M4hdi
〰️〰️〰️〰️〰️〰️〰️
©@raspberry_python
👍2
🐍 Python & Raspberry 🐍
✔️ فرض کنیم چنین سوالی داریم "میخوایم ببینیم، آیا حرف nام letters در کلمه nام words وجود داره یا نه" دو راه داریم که مشخص شدن. بدون ران کردن و تست سرعت کد، این خیلی مهمه، بگید کدوم کند‌تره؟ و برای جواب‌تون حتما دلیل بتراشید [خط سوم (choice) درست هست]…
✔️ جواب

تا حالا تریس‌بک دیدید؟ خب معلومه! اما این چه ربطی به جواب داره؟

اول بیاید یه تریس‌بک ببینیم:
Traceback (most recent call last):
File "/.../fields.py", line 241, in set
inst.data[self.name] = self.validator.validate(value)
File "/.../fields.py", line 662, in validate
raise ValidationError(messages=error_messages)
typesystem.base.ValidationError: {0: 'Must be a string.', 1: 'Must be a string.'}


هر یه دونه خطی که نوشته فلان فایل و کجا و یه خطی ازش آورده، چیزیه به اسم frame object.
هر تابعی که صدا زده میشه، توی call stack عه پایتون، یه فریم آبجکت درست میشه که استک مورد نیاز و دیکشنری ()locals عه اون و مقداری که ازش باید return بشه یا exception عی که باید ازش propagate بشه رو مدیریت میکنه، و تابع اون تو ران میشه.

یعنی return کار میکنه چون فریم آبجکت وجود داره و اون این کار رو برامون انجام میده.

وقتی پایتون یه مقداری رو به فریم دیگه ریترن میکنه، اون فریم باید از بین بره و gc و پایتون اینجا درگیرن، بساز خراب کن بساز خراب کن (که این توی توابع recursive اندکی فرق میکنه، هی فریم ساخته میشه روی هم توی استک و بعدش دونه دونه خراب میشن)

از اون طرف صدا زده شدن تابع و همین ساخته شدن فریم و اینا تبعا یه overhead عی داره و اصطلاحا function call، اندکی توی پایتون expensive هست (که البته توی پایتون ۳.۱۱ خیلی بهتر شده و تا ۳.۱۵ خیلی بهتر میشه)

روش اولی که توی صورت سوال هست، اگه گفتید چند تا تابع داره؟
1. list
2. map
+ 500 lambda

یعنی ۵۰۲ تا فانکشن کال رو فقط ما داریم می‌بینیم.

این همهههههههه فانکشن کال اتفاق میوفته

اما روش دوم

ما دو تا تابع می‌بینیم:
1. listcomp
2. zip
(اگه نمی‌دونستید باید بگم که لیست کامپری‌هنشن ها به یه تابع تبدیل میشن.)

توابعی هم که ما نمی‌بینیم، در جفت مثال‌ها داندر contains (اونجایی که l in w داریم) صدا زده میشه که، این تابع C هست:

https://github.com/python/cpython/blob/75a6441718dcbc65d993c9544e67e25bef120e82/Objects/unicodeobject.c#L10627

با یه حساب سر انگشتی:
اولی یه لیست و یه مپ و ۵۰۰ تا لامبدا و ۵۰۰ تا متد contains
و دومی یه لیست کامپری‌هنشن و یه زیپ و ۵۰۰ تا متد contains

و اگه موارد مشترک رو کم کنیم
اولی -> 502
دومی -> 2 تا

و این میشه که روش اول کندتر میشه 😁

#M4hdi

©@raspberry_python
👍7