<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های سعید</title><link>https://virgool.ir/feed/@sbabashahi</link><description>یه برنامه نویس، علاقه مند به یادگیری</description><language>fa</language><pubDate>2026-11-11 02:53:11</pubDate><image><url>https://files.virgool.ir/upload/users/70529/avatar/avatar.png</url><title>سعید</title><link>https://virgool.ir/@sbabashahi</link></image><item><title>مروری بر __slots__ در پایتون</title><link>https://virgool.ir/@sbabashahi/مروری-بر-slots-در-پایتون-peshjiiqdgf2</link><description>توی یه مقاله به اسم __slots__  برخوردم. برام سوال پیش اومد که چی هست و چه استفاده ایی داره. جمع بندی چیز هایی که خوندم رو اینجا قرار میدم. چی هست؟ بنا به تعریف نام متغیر هایی رو که توسط instance استفاده میشه رو به صورت رشته یا دنباله ای از رشته ها براش تعریف می کنیم. بدین صورت فضای مورد نیاز برای تعریف متغیر ها ذخیره میشه و از ایجاد خودکار __dict__ و __weakref__ جلوگیری میکنه.خب حالا __dict__ و __weakref__ چیه؟ همه چیز در پایتون ابجکته. کلاس, فانکشن و … . __dict__  یه دیکشنری که ویژگی های ابجکت رو در خودش ذخیره میکنه. __weakref__ یه ویژگی که امکان ارتباط ضعیف رو به ابجکت میده. ارتباط ضعیف به چه دردی میخوره؟ وقتی تنها ارتباط های باقی مونده به یه ابجکت weakref  باشه garbage callector ابجکت رو از بین میبره و فضای اون رو به چیز های دیگه اختصاص میده.حالا که چی؟ ویژگی __slots__ این امکان رو به شما میده که ویژگی هایی که ابجکت شما نیاز داره رو صراحتا بهش معرفی کنید. این کار باعث سرعت بیشتر در دسترسی به ويژگی ها و اشغال فضای کمتر میشه.نکته استفاده از __slots__ اینه که برای ممانعت از ایجاد __dict__ باید در ارث بری همه کلاس ها پیشین __slots__ رو تعریف کرده باشن و هیچ یک از اون ها __dict__ رو تعریف نکرده باشه. نکته دیگه اینه که وقتی یه ویژگی در کلاس پدر تعریف شده دیگه نیازی نیست که در کلاس فرزند هم باز تعریف بشه. البته تعریف شدنش منجر به خطا نمیشه تنها موردی که داره اینه که فضای بیشتری اشغال میشه.class Base:&#xA;    __slots__ = &#39;foo&#39;, &#39;bar&#39;&#xA;    &#xA;class Right(Base):&#xA;    __slots__ = &#39;baz&#39;,&#xA;    &#xA;class Wrong(Base):&#xA;    __slots__ = &#39;foo&#39;, &#39;bar&#39;, &#39;baz&#39;&#xA;    &#xA;&gt;&gt;&gt; from sys import getsizeof&#xA;&gt;&gt;&gt; getsizeof(Right()), getsizeof(Wrong())&#xA;(64, 80)سرعت بیشترimport timeit&#xA;&#xA;class Foo(object): __slots__ = &#39;foo&#39;,&#xA;class Bar(object): pass&#xA;&#xA;slotted = Foo()&#xA;not_slotted = Bar()&#xA;&#xA;def get_set_delete_fn(obj):&#xA;    def get_set_delete():&#xA;        obj.foo = &#39;foo&#39;&#xA;        obj.foo&#xA;        del obj.foo&#xA;    return get_set_delete&#xA;&#xA;&gt;&gt;&gt; min(timeit.repeat(get_set_delete_fn(slotted)))&#xA;0.2846834529991611&#xA;&gt;&gt;&gt; min(timeit.repeat(get_set_delete_fn(not_slotted)))&#xA;0.3664822799983085 نزدیک به ۳۰ درصد سرعت بهتر در اجرا با استفاده از __slots__ داره.صرفه جویی در حافظهتوی این قسمت بهتره این پست از sqlalchemy رو مطالعه کنید.چند نمونه از کار با __slots__class Base(object):&#xA;    __slots__ = ()&#xA;&#xA;&gt;&gt;&gt; b = Base()&#xA;&gt;&gt;&gt; b.a = &#39;a&#39;&#xA;Traceback (most recent call last):&#xA;File &#34;&lt;pyshell#38&gt;&#34;, line 1, in &lt;module&gt;&#xA;  b.a = &#39;a&#39;&#xA;  AttributeError: &#39;Base&#39; object has no attribute &#39;a&#39;وقتی از __slots__ استفاده می کنید دیگه نمیشه ویژگی که تعریف نشده رو بهش اضافه کنید. اما در صورتی که در ارث بری اون ویژگی بهش اضافه بشه مشکلی پیش نمیاد.class Child(Base):&#xA;    __slots__ = (&#39;a&#39;,)&#xA;    &#xA;c = Child()&#xA;c.a = &#39;a&#39;اگه نیاز به استفاده از __dict__ داشتید. با در نظر گرفتن اینکه شما مقداری از سرعت بیشتر و مصرف بهینه حافظه رو از دست میدین ولی میتونید به صورت پویا ویژگی به ابجکت اضافه و استفاده کنید.class SlottedWithDict(Child):&#xA;    __slots__ = (&#39;__dict__&#39;, &#39;b&#39;)&#xA;  &#xA;swd = SlottedWithDict()&#xA;swd.a = &#39;a&#39;&#xA;swd.b = &#39;b&#39;&#xA;swd.c = &#39;c&#39;&#xA;&gt;&gt;&gt; swd.__dict__&#xA;{&#39;c&#39;: &#39;c&#39;}اگه ارث بری بدون تعریف __slots__ باشه.class NoSlots(Child): pass&#xA;&#xA;ns = NoSlots()&#xA;ns.a = &#39;a&#39;&#xA;ns.b = &#39;b&#39;&#xA;&gt;&gt;&gt; ns.__dict__&#xA;{&#39;b&#39;: &#39;b&#39;}بیان کردن چند نکته خالی از لطف نیست. اگر از ابجکتی ارث بری بکنید که خودش __slots__ رو تعریف نکرده ویژگی هایی که در __slots__ تعریف بشن به صورت slot  شده قابل دسترس خواهند بود اما سایر ویژگی ها در __dict__ قرار میگیرن. همچنین اگه لازم داشتید میشه __weakref__ رو هم به __slots__ اضافه کنید.در آخر باید گفت بزرگترین ایراد استفاده از __slots__ اینه که پشتیبانی از ارث بری چندگانه رو به همراه نداره.class Foo(object):&#xA;    __slots__ = &#39;foo&#39;, &#39;bar&#39;&#xA;    &#xA;class Bar(object):&#xA;    __slots__ = &#39;foo&#39;, &#39;bar&#39; &#xA;    &#xA;&gt;&gt;&gt; class Baz(Foo, Bar): pass&#xA;Traceback (most recent call last):&#xA;File &#34;&lt;stdin&gt;&#34;, line 1, in &lt;module&gt;&#xA;  TypeError: Error when calling the metaclass bases&#xA;  multiple bases have instance lay-out conflictبخش زیادی از این پست با استفاده از مرجع نوشته شده است.</description><category>سعید</category><author>سعید</author><pubDate>Sun, 27 Oct 2019 12:32:33 +0330</pubDate></item><item><title>موقعیت جغرافیایی با drf, django و postgres</title><link>https://virgool.ir/@sbabashahi/موقعیت-جغرافیایی-با-drf-django-و-postgres-uewitmllpep3</link><description>اولین مقاله ای هست که مینویسم پس اگه موردی داشت حتما بهم گوش زد کنید :) خوشحال میشم بازخورد هاتون رو بشنوم.توی این مقاله به صورت خلاصه یه اپلیکیشن با پشتیبانی از موقعیت جغرافیایی, نقشه گرافیکی در django admin و ملزومات rest api رو شرح میدم.فرض من بر اینه که شما با پایتون, django و postgres آشنایی دارین به همین خاطر سعی کردم فقط نکات جدید و کلیدی در رابطه با موضوع مقاله رو اینجا بیان کنم. اگه آشنایی ندارید یا دوست دارید یه مقاله خوب و کامل در این رابطه بخونید مقاله سایت Digital Ocean میتونه کمکتون کنه.Spatial Database:یه دیتا بیس که برای ذخیره و بازیابی اطلاعات محیط جغرافیایی (Point, Line, Polygon) ایجاد شده. البته postgres به صورت عادی این امکان رو نداره و باید یه افزونه بهش اضافه بشه که در ادامه با هم انجام میدیم.قبل از اینکه افزونه postgres  رو بهش اضافه کنیم, چند مورد باید روی سیستم نصب بشه. این بسته ها به صورت مستقیم یا غیر مستقیم توسط کتابخانه های جغرافیایی استفاده می شن.sudo apt-get install binutils libproj-dev gdal-binمتاسفانه یا خوشبختانه من فقط نصب debian/ubuntu  رو میدونم برای mac و ویندوز به سایت مرجع رجوع شود. :) اگه نیازی به اطلاعات بیشتر برای نصب داشتید به این لینک برید.حالا باید افزونه postgis رو به postgres اضافه کنیم برای این کار به دیتابیس مد نظرتون برید و افزونه postgis رو اضافه کنید.sudo su postgres&#xA;psql &lt;db name&gt;&#xA;CREATE EXTENSION postgis; تا اینجا یکم قضیه دواپزی بود بریم قسمت دولوپری :). برای راحتی خودم :)) model رو ساده میزینم با فرض اینکه میخایم فقط یه نقطه مختصات جغرافیایی ذخیره بشه. model میشه یه همچین چیزی:from django.contrib.gis.db import models&#xA;class Location(models.Model):&#xA;     location_point = models.PointField(null=True, blank=True)&#xA;     # other fields ...&#xA;بعد از اینکه makemigration و migrate رو زدین(اسم app رو هم به settingsاصافه کنید). برای قسمت ادمین هم باید این کد ها رو داشته باشیم. با فرض اینکه اسم app ما location هست.from django.contrib import admin&#xA;from location.models import Location  # Suppose location is the name of app :)@admin.register(Location)&#xA;class LocationAdmin(admin.ModelAdmin):&#xA;    fields = ( &#39;location_point&#39;, )خب حالا ببینیم ادمین django چه شکلیاس.نقشه پیش فرض django adminبچه ها اون گربهه ایران ماست :)) این نقشه پیش فرض django هست ولی نقشه جذابی نیست چون شهر یا خیابان رو نشون نمیده. برای ساپورت باید از یه app django استفاده کنیم بین چندتایی که وجود داشت من django-location-field رو پیشنهاد میکنم. استفاده از این app هم خیلی راحته, اول اون رو در محیط پروژه نصب میکنیم.pip install django-location-fieldدر ادامه location_field.apps.DefaultConfig رو به INSTALLED_APPS در قسمت settings پروژه اضافه میکنیم. باید یه سری تنظیمات هم یه فایل settings اضافه کنیم. این افزونه google maps  رو هم ساپورت میکنه اما چون google maps api پولیه از open street map استفاده میکنیمLOCATION_FIELD = {&#xA;    &#39;map.provider&#39;: &#39;openstreetmap&#39;,&#xA;    &#39;map.zoom&#39;: 15,&#xA;&#xA;    &#39;search.provider&#39;: &#39;google&#39;,&#xA;    &#39;search.suffix&#39;: &#39;&#39;,&#xA;&#xA;    # # Google&#xA;    # &#39;provider.google.api&#39;: &#39;//maps.google.com/maps/api/js?sensor=false&#39;,&#xA;    # &#39;provider.google.api_key&#39;: &#39;&lt;INSERT GOOGLE API KEY&gt;&#39;,&#xA;    # &#39;provider.google.api_libraries&#39;: &#39;&#39;,&#xA;    # &#39;provider.google.map.type&#39;: &#39;ROADMAP&#39;,&#xA;    #&#xA;    # # Mapbox&#xA;    # &#39;provider.mapbox.access_token&#39;: &#39;&#39;,&#xA;    # &#39;provider.mapbox.max_zoom&#39;: 18,&#xA;    # &#39;provider.mapbox.id&#39;: &#39;mapbox.streets&#39;,&#xA;&#xA;    # OpenStreetMap&#xA;    &#39;provider.openstreetmap.max_zoom&#39;: 16,&#xA;&#xA;    # # misc&#xA;    # &#39;resources.root_path&#39;: LOCATION_FIELD_PATH,&#xA;    # &#39;resources.media&#39;: {&#xA;    #     &#39;js&#39;: (&#xA;    #         LOCATION_FIELD_PATH + &#39;/js/form.js&#39;,&#xA;    #     ),&#xA;    # },&#xA;} من قسمت هایی که استفاده نکردم رو کامنت کردم و گذاشتم شاید کسی بخواد استفاده کنه... حالا باید توی  Location model فیلد location_point رو تغییر بدیم با استفاده از این کد ها:from location_field.models.spatial import LocationFieldclass Location(models.Model):&#xA;    location_point = LocationField(based_fields=[&#39;city&#39;], zoom=7, default=Point(51.67, 32.65), null=True, blank=True)یه نکته ای این app یه نوع فیلد دیگه هم داره به اسم PlainLocationField که به همین منظور استفاده میشه با این تفاوت که مختصات رو توی دیتا بیس string ذخیره میکنه,  به نظر من گزینه جذابی نیست ولی میتونه به درد اونایی بخوره که به هر دلیلی نمیخان افزونه postgis رو اضافه کنن.حالا اگه ادمین رو دوباره ببینیمنقشه جدید در django adminبرای اضافه کردن  rest api به فرمت json از django rest framework استفاده میکنیم. چون توضیحات توی سایتش کامله و خارج از بحث ما میشه من فقط قسمت مربوط به serializer رو اینجا می نویسم!import json&#xA;&#xA;from django.contrib.gis.geos import Point&#xA;from rest_framework import serializers&#xA;&#xA;from location.models import Location&#xA;&#xA;class LocationSerializer(serializers.Serializer):&#xA;    location = serializers.ListField(child=serializers.DecimalField(max_digits=7, decimal_places=5), max_length=2, min_length=2)&#xA;    &#xA;    def create(self, validated_data):&#xA;        validated_data[&#39;location_point&#39;] = Point(validated_data.pop(&#39;location&#39;))&#xA;        location = Location(**validated_data)&#xA;        location.save()&#xA;        return location&#xA;        &#xA;    def update(self, instance, validated_data):&#xA;        if validated_data.get(&#39;location&#39;):&#xA;            instance.location_point = Point(validated_data.pop(&#39;location&#39;))&#xA;        return instance&#xA;&#xA;    def to_representation(self, instance):&#xA;        instance.location = json.loads(instance.location_point.geojson)[&#39;coordinates&#39;]&#xA;        instance = super().to_representation(instance)&#xA;        return instanceاین serialzier یه لیست دو تایی از اعداد اعشاری میگیره که همون latitude , longitude هستن اما باید برعکس قرار بگیرن! (به صورت long, lat ارسال بشن) این قسمتش رو خودم مطمین نیستم اما فکر میکنم ذخیره سازی براساس محور مختصات هست که در اون x, y وجود داره برای همین برعکس عرض جغرافیایی و طول جغرافیایی میشن(اگه اشتباهه و کسی درستش رو میدونه بگه تا اصلاح کنم این قسمت رو). خروجی rest  اینجوری میشه&#34;location&#34;: [&#34;51.67000&#34;,&#34;32.65000&#34;]و قاعدتا برای ساخت و آپدیت هم همینجوری باید ارسال بشه. انتخاب نام location برای serializer و location_point برای model هم به این دلیله که موقع create و update فیلد point که در دیتابیس هست به لیست اعداد توی rest api تبدیل بشه. اگه روش بهتری وجود داره گوش زد کنید:).  </description><category>سعید</category><author>سعید</author><pubDate>Tue, 01 Oct 2019 00:28:59 +0330</pubDate></item></channel></rss>